• 设计模式--观察者模式


          观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

      观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

    观察者模式的结构

      一个软件系统里面包含了各种对象,就像一片欣欣向荣的森林充满了各种生物一样。在一片森林中,各种生物彼此依赖和约束,形成一个个生物链。一种生物的状态变化会造成其他一些生物的相应行动,每一个生物都处于别的生物的互动之中。

      同样,一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其他的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作。观察者模式是满足这一要求的各种设计方案中最重要的一种。

      下面以一个简单的示意性实现为例,讨论观察者模式的结构。

      观察者模式所涉及的角色有:

      ●  抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。

      ●  具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。

      ●  抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。

      ●  具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

    接下来用订阅战报纸的小例子来理解一下观察者模式  出版者+订阅者=观察者模式

    报纸接口:
    public interface IPaper {
        //添加订阅者
        public void registerSubscriber(IPeople subscriber);
        //取消订阅
        public void removeSubscriber(IPeople subscribe);
        //发送报纸
        public void sendNewPaper();
    }
    
    订阅者接口:
    public interface IPeople {
    
        //有新的报纸后进行通知
        public void hasNewPaper(IPaper ipaper);
    }
    
    报纸接口实现类:
    public class Paper implements IPaper{
    
        /**
         * 用来保存注册的观察者对象
         */
        List<IPeople> peopleList;
        
        //用来保存新的报纸
        List<String> newPaperList;
        
        public Paper(){
            peopleList = new ArrayList<IPeople>();
             newPaperList = new ArrayList<String>();
        }
        
        //先把观察者对象都 加入到 List 中,然后再遍历这些对象,调用它们的方法通知这些观察者
        //注册观察者对象
        @Override
        public void registerSubscriber(IPeople subscriber) {
            // TODO Auto-generated method stub
            peopleList.add(subscriber);
        }
    
        //删除观察者对象
        @Override
        public void removeSubscriber(IPeople subscribe) {
            // TODO Auto-generated method stub
            if(peopleList.indexOf(subscribe) > 0){
                peopleList.remove(subscribe);
            }
        }
    
        //通知所有注册的观察者对象
        @Override
        public void sendNewPaper() {
            // TODO Auto-generated method stub
            for (IPeople subscriber : peopleList) {
                subscriber.hasNewPaper(this);
            }
        }
        
        public void addPaper(String newPaper){
            this.newPaperList.add(newPaper);
            sendNewPaper();
        }
        
        public String toString(){
            return newPaperList.toString();
        }
    
    }
    
    订阅者实现类:
    public class People implements IPeople{
    
        private String    peopleName;
        
        public People(String peopleName) {
            this.peopleName = peopleName;
        }
    
        //告诉订阅者新报纸到了
        @Override
        public void hasNewPaper(IPaper ipaper) {
            // TODO Auto-generated method stub
            System.out.println(peopleName + ",您好,您的新战报到了!");
            System.out.println(ipaper);
        }
    
    }
    
    测试(当被观察者状态改变时,通知用户):
    public class Test {
    
        public static void main(String[] args) {
            
            //被观察者 新闻报纸
            Paper paper = new Paper();
            
            //观察者 订户
            People fujian = new People("苻坚");
            People murong = new People("慕容燕");
            People wangmeng = new People("王猛");
            
            paper.registerSubscriber(fujian);
            paper.registerSubscriber(murong);
            paper.registerSubscriber(wangmeng);
            
            //添加新的报纸,添加后被观察者自动通知各用户
            paper.addPaper("东晋战报");
            System.out.println("-------战报已全部发送------");
            
            paper.removeSubscriber(murong);    //去掉一个观察者
            paper.newPaperList.clear();
            paper.addPaper("北燕战报");
            
        }
    }

    结果:

    参考资料:

    http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html

    http://www.cnblogs.com/li-peng/archive/2013/02/04/2892116.html

  • 相关阅读:
    leetcode回溯46
    多线程第五节_AQS
    leetcode1254
    leetcode214最大路径和
    leetcode200dfs岛屿的数量
    leetcode51n皇后
    多线程第三节_mesi
    ElasticSearch基本使用姿势二
    我的 Java 学习&面试网站又又又升级了!
    SpringBoot + JWT + Redis 开源知识社区系统
  • 原文地址:https://www.cnblogs.com/fengbing9891/p/5291397.html
Copyright © 2020-2023  润新知