если мы предполагаем, что точка x больше, чем точка y, если угол, который это имеет с точкой (0,0), больше тогда, мы можем реализовать этот этот путь в c#
class Point : IComparable<Point>
{
public int X { set; get; }
public int Y { set; get; }
public double Angle
{
get
{
return Math.Atan2(X, Y);
}
}
#region IComparable<Point> Members
public int CompareTo(Point other)
{
return this.Angle.CompareTo(other.Angle);
}
#endregion
public static List<Point> Sort(List<Point> points)
{
return points.Sort();
}
}
Если вы хотите избежать наследования от базового класса, подобного java.util.Observable, используйте интерфейс и позвольте вашим наблюдаемым объектам реализовывать или делегировать методы интерфейса.
Вот наблюдаемый интерфейс :
public interface IObservable
{
void addObserver(IObserver o);
void deleteObserver(IObserver o);
void notifyObservers(INotification notification);
}
Вот вспомогательный класс, который может использоваться вашими реальными наблюдаемыми:
import java.util.ArrayList;
import java.util.List;
public class Observable implements IObservable
{
private List<IObserver> observers;
@Override
public synchronized void addObserver(IObserver o)
{
if (observers == null)
{
observers = new ArrayList<IObserver>();
}
else if (observers.contains(o))
{
return;
}
observers.add(o);
}
@Override
public synchronized void deleteObserver(IObserver o)
{
if (observers == null)
{
return;
}
int idx = observers.indexOf(o);
if (idx != -1)
{
observers.remove(idx);
}
}
@Override
public synchronized void notifyObservers(INotification notification)
{
if (observers == null)
{
return;
}
for (IObserver o : observers)
{
o.update(notification);
}
}
}
Настоящая наблюдаемая может выглядеть так:
class Person implements IObservable
{
private final IObservable observable = new Observable();
@Override
public void setFirstName(String firstName) throws Exception
{
if (firstName == null || firstName.isEmpty())
{
throw new Exception("First name not set");
}
this.firstName = firstName;
notifyObservers(new Notification(this, getFirstNamePropertyId()));
}
@Override
public void addObserver(IObserver o)
{
observable.addObserver(o);
}
@Override
public void deleteObserver(IObserver o)
{
observable.deleteObserver(o);
}
@Override
public void notifyObservers(INotification notification)
{
observable.notifyObservers(notification);
}
private static final String FIRSTNAME_PROPERTY_ID = "Person.FirstName";
@Override
public String getFirstNamePropertyId()
{
return FIRSTNAME_PROPERTY_ID;
}
}
Вот интерфейс наблюдателя:
public interface IObserver
{
void update(INotification notification);
}
Наконец, вот интерфейс уведомлений и базовая реализация:
public interface INotification
{
Object getObject();
Object getPropertyId();
}
public class Notification implements INotification
{
private final Object object;
private final Object propertyId;
public Notification(Object object, Object propertyId)
{
this.object = object;
this.propertyId = propertyId;
}
@Override
public Object getObject()
{
return object;
}
@Override
public Object getPropertyId()
{
return propertyId;
}
}
Предполагая, что переданное целое число является частью состояния класса Animal, идиоматический способ сделать это вместо написания большого количества собственного кода - запустить ] PropertyChangeEvent
. Для этого можно использовать класс PropertyChangeSupport
, сократив код до следующего:
public class Animal {
// Create PropertyChangeSupport to manage listeners and fire events.
private final PropertyChangeSupport support = new PropertyChangeSupport(this);
private int foo;
// Provide delegating methods to add / remove listeners to / from the support class.
public void addPropertyChangeListener(PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
support.removePropertyChangeListener(l);
}
// Simple example of how to fire an event when the value of 'foo' is changed.
protected void setFoo(int foo) {
if (this.foo != foo) {
// Remember previous value, assign new value and then fire event.
int oldFoo = this.foo;
this.foo = foo;
support.firePropertyChange("foo", oldFoo, this.foo);
}
}
}
Наконец, я бы не советовал использовать Observer
/ Observable
так как это делает код нечитаемым / трудным для понимания: вам постоянно приходится проверять тип аргумента, переданного Observer
, используя instanceof
перед его понижением, и трудно увидеть, какой тип события ожидает конкретная реализация Observer, глядя на определение его интерфейса.
Простой интерфейс событий выглядит следующим образом:
public interface AnimalListener {
public void animalDoesSomething(int action);
}
Animal
должен управлять своими слушателями:
public class Animal {
private final List<AnimalListener> animalListeners = new ArrayList<AnimalListener>()
public void addAnimalListener(AnimalListener animalListener) {
animalListeners.add(animalListener);
}
}
Ваш класс, создающий Animal
, должен делать следующее:
public class AnimalCreator implements AnimalListener {
public void createAnimal() {
Animal animal = new Animal();
animal.addAnimalListener(this); // implement addListener in An
}
public void animalDoesSomething(int action) {
System.ot.println("Holy crap, animal did something!");
}
}
Теперь Animal
может запускать события.
public class Animal {
....
public void doSomething() {
for (AnimalListener animalListener : animalListeners) {
animalListener.animalDoesSomething(4);
}
}
}
Это похоже на большой объем кода для чего-то столь же простого, как «запуск событий», но, возможно, запуск событий совсем не прост. :)
Конечно, у этого простого механизма есть различные расширения.
java.util.EventListener
. public void animalDoesSomething (Animal animal, int action);
. РЕДАКТИРОВАТЬ: подход Адамски PropertyChangeSupport
, основанный на подходе Адамски, кажется лучше Наблюдаемый, который я предложил.
Классы Observer / Observable присутствуют в Java с первого дня. К сожалению, первоначальные дизайнеры несколько облажались. Честно говоря, у них не было возможности поучиться на 10-летнем опыте работы с Java ...
Я решаю вашу проблему с делегированием. У меня есть собственная реализация Observer / Observable - и я рекомендую это. Но вот подход, который работает:
import java.util.Observable;
import java.util.Observer;
public class Animal {
private final ImprovedObservable observable = new ImprovedObservable();
public void addObserver(Observer o) {
observable.addObserver(o);
}
public void notifyObservers() {
observable.notifyObservers();
}
public void doSomething() {
observable.setChanged();
observable.notifyObservers(new AnimalEvent());
}
}
// simply make setChanged public, and therefore usable in delegation
class ImprovedObservable extends Observable {
@Override
public void setChanged() {
super.setChanged();
}
}
class AnimalEvent {
}
Мое первое предложение - взглянуть на AspectJ. Это один из шаблонов проектирования, с которым язык лучше всего справляется. В следующей статье очень красноречиво описывается, как это можно реализовать:
http://www.ibm.com/developerworks/java/library/j-aopwork6/index.html
Существуют также замечательные библиотеки Spring , которые предоставляют готовую структуру событий .