美文网首页
观察者模式 一

观察者模式 一

作者: zjxchase | 来源:发表于2020-03-21 22:37 被阅读0次

    简单实例

    首先看一个警察蹲点抓小偷的简单实例:警察蹲点观察到小偷偷东西就立即抓捕

    Policemen.Java (警察)

    public class Policemen implements Observer {
    
        /**
         * 警察姓名
         */
        private String name;
    
        public Policemen(String name) {
            this.name = name;
        }
    
        @Override
        public void update(Observable o, Object arg) {
            Pickpocket pickpocket = (Pickpocket) o;
    
            System.out.printf("警察 %s 发现(实际是被通知)扒手 %s 盗取了 %s,立即抓捕 \n", this.name, pickpocket.getName(), arg);
        }
    }
    

    Pickpocket.java (扒手)

    public class Pickpocket extends Observable {
    
        /**
         * 小偷姓名
         */
        private String name;
    
        /**
         * 赃物
         */
        private List<String> booties = new ArrayList<>();
    
        public Pickpocket(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        /**
         * 偷窃
         * @param booty
         */
        public void steal(String booty) {
            booties.add(booty);
    
            setChanged();
            notifyObservers(booties);
        }
    }
    

    ObserverEx1Test.java (测试类)

    public class ObserverEx1Test {
    
        public static void main(String[] args) {
            Policemen p1 = new Policemen("警察A");
            Policemen p2 = new Policemen("警察B");
            Pickpocket pp1 = new Pickpocket("郭某");
    
            pp1.addObserver(p1);
            pp1.addObserver(p2);
    
            pp1.steal("cellphone");
        }
    }
    

    运行ObserverEx1Test类输出结果:

    警察 警察B 发现(实际是被通知)郭某 盗取了 [cellphone] ,立即抓捕
    警察 警察A 发现(实际是被通知)郭某 盗取了 [cellphone] ,立即抓捕
    

    上边这种例子观察者模式叫:发布-订阅模式

    观察者模式介绍

    定义

    观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

    意图

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    解决的问题

    一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

    优点

    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
    • 目标与观察者之间建立了一套触发机制。

    缺点

    • 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
    • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

    使用场景

    • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
    • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
    • 一个对象必须通知其他对象,而并不知道这些对象是谁。
    • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

    简单实例 二

    由于java.util.Observable 和 java.util.Observer 类在java9 之后过期了,该实例主要是不再继承java.util.Observable 和 java.util.Observer 实现观察者模式

    IObserver.java 接口

    public interface IObserver {
    
        /**
         * 观察者获得消息
         * @param msg
         */
        void update(String msg);
    }
    

    ISubject.java 接口

    public interface ISubject {
    
        /**
         * 注册观察者
         * @param observer
         */
        void registerObserver(IObserver observer);
    
        /**
         * 取消观察者
         * @param observer
         */
        void removeObserver(IObserver observer);
    
        /**
         * 通知观察者
         */
        void notifyObserver();
    
        /**
         * 获取主体标示名称
         * @return
         */
        String getName();
    
    }
    

    Pickpocket.java

    public class Pickpocket implements ISubject {
    
        /**
         * 小偷姓名
         */
        private String name;
    
        /**
         * 赃物
         */
        private String booty;
    
        /**
         * 观察者集合
         */
        private List<IObserver> observers = new ArrayList<>();
    
        public Pickpocket(String name) {
            this.name = name;
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        @Override
        public void registerObserver(IObserver observer) {
            observers.add(observer);
        }
    
        @Override
        public void removeObserver(IObserver observer) {
            if (observers.contains(observer)) {
                observers.remove(observer);
            }
        }
    
        @Override
        public void notifyObserver() {
            for (IObserver observer : observers) {
                observer.update(booty);
            }
        }
    
        /**
         * 盗取赃物后给观察者(警察)发送消息
         * @param booty
         */
        public void steal(String booty) {
            this.booty = booty;
            // 通知观察者
            notifyObserver();
        }
    
    }
    

    Policemen.java

    public class Policemen implements IObserver {
    
        /**
         * 警察姓名
         */
        private String name;
    
        /**
         * 增具体的观察者订阅的主体
         */
        private ISubject subject;
    
        public Policemen(String name, ISubject subject) {
            this.name = name;
            this.subject = subject;
            subject.registerObserver(this);
        }
    
        @Override
        public void update(String booty) {
    
            System.out.printf("警察 %s 发现(实际是被通知)%s 盗取了 %s ,立即抓捕\n", this.name, subject.getName(), booty);
        }
    }
    

    ObserverEx1Test.java

    public class ObserverEx1Test {
    
        public static void main(String[] args) {
            Pickpocket pp = new Pickpocket("Pickpocket-A");
    
            Policemen p1 = new Policemen("Policemen-A", pp);
            Policemen p2 = new Policemen("Policemen-B", pp);
    
            pp.steal("手机");
    
            System.out.println("------------------------");
            pp.removeObserver(p2);
            pp.steal("PAD");
        }
    }
    

    执行结果:

    警察 Policemen-A 发现(实际是被通知)Pickpocket-A 盗取了 手机 ,立即抓捕
    警察 Policemen-B 发现(实际是被通知)Pickpocket-A 盗取了 手机 ,立即抓捕
    ------------------------
    警察 Policemen-A 发现(实际是被通知)Pickpocket-A 盗取了 PAD ,立即抓捕
    

    相关文章

      网友评论

          本文标题:观察者模式 一

          本文链接:https://www.haomeiwen.com/subject/lkfeyhtx.html