zoukankan      html  css  js  c++  java
  • 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)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者。

  • 相关阅读:
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
    自考感悟,话谈备忘录模式
    [每日一题] OCP1z0-047 :2013-07-26 alter table set unused之后各种情况处理
    Java实现 蓝桥杯 算法提高 p1001
    Java实现 蓝桥杯 算法提高 拿糖果
    Java实现 蓝桥杯 算法提高 拿糖果
    Java实现 蓝桥杯 算法提高 求arccos值
    Java实现 蓝桥杯 算法提高 求arccos值
    Java实现 蓝桥杯 算法提高 因式分解
    Java实现 蓝桥杯 算法提高 因式分解
  • 原文地址:https://www.cnblogs.com/Zender/p/7443861.html
Copyright © 2011-2022 走看看