7,观察者模式

一,概念

Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。观察者模式多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。

二,例子

四个要素

抽象被观察者(Subject):被观察的对象的接口。包含操作规范。

具体被观察者(ConcreteSubject):被观察者的具体实现。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。具体被观察者需要维持(添加,删除,通知)一个观察者对象的队列列表。

抽象观察者(Observer):接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。

具体观察者(ConcreteObserver):观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

例子1:使用java.util包下的Observable,Observer实现观察者模式

实体类:Blog

/**
 * 
 * @类名称:Blog
 * @类描述:实体类
 * @创建人:zender
 */
public class Blog {
    private String title;
    private String content;
    public Blog(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;
    }
}

被观察者:BlogSubject

setChange()方法用来设置一个内部标志位注明数据发生了变化;

notifyObservers()方法会去调用观察者对象列表中所有的Observer的update()方法,通知它们数据发生了变化。

只有在setChange()被调用后,notifyObservers()才会去调用update()。

/**
 * 
 * @类名称:BlogSubject
 * @类描述:被观察者
 * @创建人:zender
 */
public class BlogSubject extends Observable{
    public void publishBlog(String title,String content){
        Blog b = new Blog(title,content);
        System.out.println("博主:发表新文章,文章标题:" + title + ",文章内容:" + content);
        //setChanged方法标志着该对象更变。 hasChanged方法返回true。
        this.setChanged();
        //notifyObservers()方法会去调用一个列表中所有的Observer的update()方法,通知它们数据发生了变化。
        this.notifyObservers(b);
    }
}

观察者:BlogObserverOne,BlogObserverTwo

方法:update(Observable o, Object arg)

形参Object arg,对应一个由notifyObservers(Object arg);传递来的参数,当执行的是notifyObservers();时,arg为null。

/**
 * 
 * @类名称:BlogObserverOne
 * @类描述:观察者1
 * @创建人:zender
 */
public class BlogObserverOne implements Observer{
    @Override
    public void update(Observable o, Object arg) {
        Blog b = (Blog) arg;
        System.out.print("BlogObserverOne:博主发表了新的文章:");
        System.out.print("标题为:“" + b.getTitle() +"”");
        System.out.println(",内容为:“" + b.getContent()+ "”");
    }
}
/**
 * 
 * @类名称:BlogObserverTwo
 * @类描述:观察者2
 * @创建人:zender
 */
public class BlogObserverTwo implements Observer{
    @Override
    public void update(Observable o, Object arg) {
        Blog b = (Blog) arg;
        System.out.print("BlogObserverTwo:博主发表了新的文章:");
        System.out.print("标题为:“" + b.getTitle() +"”");
        System.out.println(",内容为:“" + b.getContent()+ "”");
    }
}

测试:

/**
 * 
 * @类名称:Test
 * @类描述:测试
 * @创建人:zender
 */
public class Test {
 
    public static void main(String[] args) {
        BlogSubject cs = new BlogSubject();
        BlogObserverOne one = new BlogObserverOne();
        BlogObserverTwo two = new BlogObserverTwo();
        cs.addObserver(one);
        cs.addObserver(two);
        cs.publishBlog("内容1","这是我写的内容1");
        //移除订阅者1
        cs.deleteObserver(one);
        System.out.println("----------------");
        cs.publishBlog("文章2", "这是我写的内容2");
    }
}

结果:

例子2:手动实现观察者模式

抽象观察者(ObServer):MyObserver

/**
 * 
 * @类名称:MyObserver
 * @类描述:抽象观察者(ObServer)
 * @创建人:zender
 */
public interface MyObServer {
    public void update(String message);
}

具体观察者(ConcrereObserver):BlogUser

/**
 * 
 * @类名称:BlogUser
 * @类描述:具体观察者(ConcrereObserver)
 * @创建人:zender
 */
public class BlogUser implements MyObServer {
    //博客用户名称
    private String name;
 
    public BlogUser(String name) {
        super();
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        System.out.println(name + "您关注的博客更新了:" + message);
    }
}

抽象被观察者(Subject):MySubject

/**
 * 
 * @类名称:MySubject
 * @类描述:抽象被观察者(Subject)
 * @创建人:zender
 */
public interface MySubject {
    /**
     * 增加订阅者
     */
    public void attach(MyObServer observer);
    /**
     * 删除订阅者
     */
    public void detach(MyObServer observer);
    /**
     * 通知订阅者更新消息
     */
    public void notify(String message);
}

具体被观察者(ConcreteSubject):BlogSubject

/**
 * 
 * @类名称:BlogSubject
 * @类描述:具体被观察者(ConcreteSubject)
 * @创建人:zender
 */
public class BlogSubject implements MySubject{
    //存储订阅者的List
    private List<MyObServer> blogUserList = new ArrayList<MyObServer>();
    
    @Override
    public void attach(MyObServer observer) {//添加订阅者
        blogUserList.add(observer);
    }
 
    @Override
    public void detach(MyObServer observer) {//删除订阅者
        blogUserList.remove(observer);
    }
 
    @Override
    public void notify(String message) {//循环通知订阅者
        for (MyObServer myObServer : blogUserList) {
            myObServer.update(message);
        }
    }
}

测试:

/**
 * 
 * @类名称:Test
 * @类描述:测试类
 * @创建人:zender
 */
public class Test {
 
    public static void main(String[] args) {
        BlogSubject bs = new BlogSubject();
        //1,创建用户
        BlogUser user1 = new BlogUser("张三");
        BlogUser user2 = new BlogUser("李四");
        BlogUser user3 = new BlogUser("王伟");
        //2,订阅Blog
        bs.attach(user1);
        bs.attach(user2);
        bs.attach(user3);
        //3,发布Blog
        bs.notify("zender-Blog更新了。");
        System.out.println("--------------------");
        //移除订阅者
        bs.detach(user3);
        bs.notify("zender-Blog又更新了。");
    }
}

结果:

三、观察者模式的典型应用

1,侦听事件驱动程序设计中的外部事件。

2,侦听/监视某个对象的状态变化。

3,发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者。

posted @ 2017-08-28 15:08  Zender  阅读(473)  评论(0编辑  收藏  举报