• 9,观察者模式


    一,概念

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

  • 相关阅读:
    2018.7.9 模拟赛
    树状数组||归并排序求逆序对+离散化 nlogn
    LCS nlogn
    孤岛营救问题
    [POJ 3621] Sighting Cows
    树状数组求LIS
    nlogn求逆序对&&陌上花开
    最长可重区间集
    LCA模板
    [BZOJ] 4196 [Noi2015]软件包管理器
  • 原文地址:https://www.cnblogs.com/Zender/p/7483473.html
Copyright © 2020-2023  润新知