在Observer Design模式中,Subject和Observable是同一个东西吗?

时间:2015-10-01 04:51:17

标签: java class design-patterns observable subject

在观察者设计模式中,观察者观察主体和/或观察者。观察者会收到更新通知。

我很困惑这两件事(主题和可观察的)是否基本相同?或者这两者之间有细微差别吗?

4 个答案:

答案 0 :(得分:6)

只要一个或多个观察者必须观察一个主体,就可以使用观察者设计模式。

Observable - 定义将观察者附加到客户端和取消附加操作的接口或抽象类。在GOF书中,此类/界面称为主题

它们基本相同。

答案 1 :(得分:2)

是的,两者都相同。

观察者可以观察到主体。 Subject保留一个观察者列表,以便它可以通知这些观察者任何状态变化。

查看以下Python代码,取自Wikipedia

class Observable:
    def __init__(self):
        self.__observers = []

    def register_observer(self, observer):
        self.__observers.append(observer)

    def notify_observers(self, *args, **kwargs):
        for observer in self.__observers:
            observer.notify(self, *args, **kwargs)


class Observer:
    def __init__(self, observable):
        observable.register_observer(self)

    def notify(self, observable, *args, **kwargs):
        print('Got', args, kwargs, 'From', observable)


subject = Observable()
observer = Observer(subject)
subject.notify_observers('test')

enter image description here

答案 2 :(得分:1)

主题和观察者是两个不同的实体(对象):

但关于你的问题,

  

观察者观察主体或可观察的

     

主题的另一个名称是可观察的,因此它们是相同的

主题维护一个观察者列表,所有观察者都在主题处注册。 因此,无论何时某个事件发生在主题上,他都会通知所有观察者。

  

示例:

假设您有一个名为HTTPEngine的类,它处理所有与HTTP相关的内容(连接,数据撤销等)。

为了让HTTPEngine可以在不同的对象之间重用,它维护了一个说IHTTPObserver的列表。

因此,任何希望使用HTTPEngine的对象都实现接口HTTPObserver,在HTTPEngine上注册,然后收到事件通知。

例如:

class HTTPObserver
{
 public:
 virtual void onEvent() = 0;

}

所以,请说一个名为"客户"的课程。想要使用HTTPENgine。

class client: public HTTPObserver
{
  void onEvent(){//got the event notification}
}

现在,HTTPENgine维护一个观察者列表:

class HTTPEngine
{
private:
 vector<IHTTPObserver*> clients;
public:
 void register(IHTTPObserver* client){clients.push_back(client);} 
 void notifyclients(){
 for(it=vector.begin();it!=Vector.end();it++)
 (*it)->notifyEvent();}

};

答案 3 :(得分:0)

  

使用一对多关系时使用观察者设计模式   并且如果更新了主对象,则更新依赖对象.Observer   patter是行为设计​​模式的一个例子。它有三个   演员这样的主要类,依赖超类和它的子类。

请查看以下观察者设计模式的UML图。

enter image description here

  1. Circle类是主类。它有一个 特殊属性观察员,保持所有观察者的圈子。它可以附加(或根据需要重新附加)观察者。
  2. Observer类是超类依赖项。它是一个抽象类,为Circle类提供常用方法。
  3. 儿童观察员班级(AreaObserverPerimeterObserver)是主要班级(Circle
  4. 的家属
  5. 我使用ObserverExample来测试示例。它不是Observer设计模式的内容。
  6. <强> Circle.java

    public class Circle {
    
        private List<Observer> observers;
        private double radius;
    
        public Circle() {
            observers = new ArrayList<>();
        }
    
        public double getRadius() {
            return radius;
        }
    
        public void setRadius(double radius) {
            this.radius = radius;
            notifyObservers();
        }
    
        /**
         * attach an observer to the circle
         */
        public void attach(Observer observer) {
            observers.add(observer);
        }
    
        /**
         * notify all observers on update
         */
        public void notifyObservers() {
            for (Observer observer : observers) {
                observer.update();
            }
        }
    }
    

    <强> Observer.java

    public abstract class Observer {
    
        protected Circle circle;
    
        public Observer(Circle circle) {
            this.circle = circle;
        }
    
        public abstract void update();
    }
    

    <强> AreaObserver.java

    public class AreaObserver extends Observer {
    
        public AreaObserver(Circle circle) {
            super(circle);
        }
    
        @Override
        public void update() {
            System.out.printf("New area is: %f\n", Math.PI * circle.getRadius() * circle.getRadius());
        }
    }
    

    <强> PerimeterObserver.java

    public class PerimeterObserver extends Observer {
    
        public PerimeterObserver(Circle circle) {
            super(circle);
        }
    
        @Override
        public void update() {
            System.out.printf("New Perimeter is: %f\n", 2 * Math.PI * circle.getRadius());
        }
    }
    

    <强> ObserverExample.java

    public class ObserverExample {
    
        public static void main(String[] args) {
            Circle circle = new Circle();
    
            PerimeterObserver perimeterObserver = new PerimeterObserver(circle);
            circle.attach(perimeterObserver);
    
            AreaObserver areaObserver = new AreaObserver(circle);
            circle.attach(areaObserver);
    
            System.out.println("Set radius: 7.0");
            System.out.println("---------------");
            circle.setRadius(7.0);
    
            System.out.println();
    
            System.out.println("Set radius: 5.0");
            System.out.println("---------------");
            circle.setRadius(5.0);
        }
    }
    

    <强>输出:

    Set radius: 7.0
    ---------------
    New Perimeter is: 43.982297
    New area is: 153.938040
    
    Set radius: 5.0
    ---------------
    New Perimeter is: 31.415927
    New area is: 78.539816
    

    根据输出,似乎所有观察者在更新主类时都会更新。