大话设计模式:观察者模式

观察者模式:

    官方定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所依赖者都会收到通知并自动更新。

    理解:观察者模式在生活中的例子像在头条中关注了某好友,当好友发布消息时,系统第一时间将信息全部推送给我(推模型),或者只传递消息的部分,自己手动获取另外的部分(拉模型),这样保证了当好友有动态时,我能够收到消息。像这个例子中,可以有两种方式获得消息,其实在观察者模式中提供了两种不同的模型分别是推、拉模型。相当于头条两种发消息方式,第一:发送全部消息内容,第二:发送关键信息,点击关键信息可以查看全部内容。

    观察者的角色

      抽象观察者接口:注册到主题上,当主题改变时,会得到主题发送的消息。

      抽象主题接口:维护一个观察者的集合,观察者可以在集合中注册和移除,当有消息发送时,主题会遍历所有的观察者,发送消息。

      具体观察者:实现抽象观察者,在类内部可以自定义相关符合业务逻辑内容。

      具体主题:具体实现抽象主题,实现具体发送观察者消息的方法。

    拉模式:

public class Message {
    private String title;
    private String content;

    @Override
    public String toString() {
        return "Message{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    public Message() {
    }

    public Message(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
Message,消息实体类
/**
 * 主题接口:
 */
public interface Subject {
    void register(Observer o);//注册观察者
    void remove(Observer o);//移除观察者
    void update();//向观察者发消息
}
抽象主题类
public class SubjectImpl implements Subject {
    private Message msg;
    private List<Observer> list;

    public Message getMsg() {
        return msg;
    }

    public SubjectImpl(){
        list = new ArrayList<Observer>();
    }
    @Override
    public void register(Observer o) {
        if(!list.contains(o))
           list.add(o);
    }

    @Override
    public void remove(Observer o) {
        list.remove(o);
    }

    /**
     * 当有消息时,遍历观察者发送消息
     * @param msg
     */
    public void setMsg(Message msg) {
        this.msg = msg;
        update();
    }

    @Override
    public void update() {
        for(Observer observer:list){
            observer.pull(this);
        }
    }
}
主题实现类
public interface Observer {
    void pull(Subject subject);
}
抽象观察者类
public class ObserverImpl implements Observer {
    public ObserverImpl(String name) {
        this.name = name;
    }

    private String name;//观察者的名字


    @Override
    public void pull(Subject subject) {
        Message msg = ((SubjectImpl) subject).getMsg();
        System.out.println(name+"--title"+msg.getTitle()+"--content"+msg.getContent());
    }
}
观察者实现类
public class Main {
    public static void main(String[] args) {
        Message message = new Message("测试观察者的pull模式","怎样测试观察者poll模式?。。。。。。");
        ObserverImpl observer1 = new ObserverImpl("观察者1");
        ObserverImpl observer2 = new ObserverImpl("观察者2");
        SubjectImpl sub= new SubjectImpl();
        sub.register(observer1);
        sub.register(observer2);
        sub.setMsg(message);
    }
}
测试类

    在代码中,我们能够感觉到,可以吧抽象主题类由接口转换为抽象类,这样在具体实现类中只需要把消息置入主题中即可。

    在拉模式下,主题像观察者只发送少量的关键信息,在实际的上,往往是关键字绑定url链接的方式。

    拉模式有点包括:接收信息量少,信息发送快。

    推模式:

/**
 * 主题接口:
 */
public interface Subject {
    void register(Observer o);//注册观察者
    void remove(Observer o);//移除观察者
    void update();//向观察者发消息
}
抽象主题类
public class SubjectImpl implements Subject {
    private Message msg;
    private List<Observer> list;

    public Message getMsg() {
        return msg;
    }

    public SubjectImpl(){
        list = new ArrayList<Observer>();
    }
    @Override
    public void register(Observer o) {
        if(!list.contains(o))
           list.add(o);
    }

    @Override
    public void remove(Observer o) {
        list.remove(o);
    }

    public void setMsg(Message msg) {
        this.msg = msg;
        update();
    }

    @Override
    public void update() {
        for(Observer observer:list){
            observer.push(msg);
        }
    }
}
主题实现类
public interface Observer {
    void push(Message msg);
}
抽象观察者
public class ObserverImpl implements Observer {
    public ObserverImpl(String name) {
        this.name = name;
    }

    private String name;//观察者的名字


    @Override
    public void push(Message msg) {
        System.out.println(msg);
    }
}
观察者实现
public class Main {
    public static void main(String[] args) {
        Message message = new Message("测试观察者的push模式","怎样测试观察者push模式?。。。。。。");
        ObserverImpl observer1 = new ObserverImpl("观察者1");
        ObserverImpl observer2 = new ObserverImpl("观察者2");
        SubjectImpl sub= new SubjectImpl();
        sub.register(observer1);
        sub.register(observer2);
        sub.setMsg(message);
    }
}
推模式测试类

    在代码中明显感觉接受者接受的消息可能会变多,但是这样发送消息和接受消息简单。

    只需要将消息全部发出和全部接受即可,操作简单。

观察者模式在JAVA

    主题对应:java.util.Observable

    观察者对应:java.util.Observer

在java中,主题对应的Observable对应是是一个普通类,而不是抽象类或接口,方法中使用synchronized关键字,效率不高,因为不是接口,所以要用继承不能用组合。如果有必要可以自己手动实现主题。

 

posted @ 2019-03-12 16:09  i孤独行者  阅读(331)  评论(0编辑  收藏  举报