zoukankan      html  css  js  c++  java
  • 设计模式-观察者模式

    1.什么是观察者模式

    观察者模式(Observer Pattern)又称为发布/订阅模式,  属于行为型模式。

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

    自己理解 一个事情随着另一件事情发生变化 , 两个事情存在内在联系  ,一个是观察者 , 另一个是被观察者。

    2.为什么要用观察者模式

    一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知,而不用一个个的进行通知,达到对象依赖关系弱化。

    3.怎么用观察者模式

    例子1

        用户收到人民日报公众号发布房价上涨的消息的不同反应

    被观察者  人民日报公众号

    观察者   用户

    public class ObserverPatternTest {
    
        public static void main(String[] args) {
    
                //开始运营订阅号
                WeChatSubscribe subject = new PeopleDaily();
                //用户都已经注册
                AbstractUser obs1 = new ZhangSan();
                AbstractUser obs2 = new LiSi();
                //用户陆续关注
                subject.add(obs1);
                subject.add(obs2);
                //通知已经关注的用户
                subject.notifyObserver();
            }
    
    }
    
    /***
     *功能描述  观察者-----------抽象观察者
     */
    abstract class AbstractUser {
        /***
         *  抽象反应,每个人反应不一样,有的吃惊,有的高兴
         */
        abstract void response();
    }
    
    /***
     *功能描述  观察者-----------具体观察者---张三
     */
    class ZhangSan extends AbstractUser {
        @Override
        public void response() {
            System.out.println("张三作为具体观察者,听了很伤心");
        }
    }
    
    /***
     *功能描述  被观察者-----------具体观察者---李四
     */
    class LiSi extends AbstractUser {
        @Override
        public void response() {
            System.out.println("李四作为具体观察者,听了很高兴");
        }
    }
    
    
    
    
    
    /***
     *功能描述  被观察者-----------抽象目标,微信订阅号
     */
    abstract class WeChatSubscribe {
        /***
         *  定义观察者集合,用于增加、删除订阅者(观察者),可被覆写延迟到子类中实现
         */
        protected List<AbstractUser> observers = new ArrayList<AbstractUser>();
    
        /***
         *  增加观察者方法,可进行抽象,延迟到子类中实现
         */
    
        public void add(AbstractUser observer) {
            observers.add(observer);
        }
    
        /***
         *  删除观察者方法,可进行抽象,延迟到子类中实现
         */
        public void remove(AbstractUser observer) {
            observers.remove(observer);
        }
    
        /***
         *  通知观察者方法
         */
        public abstract void notifyObserver();
    }
    
    
    /***
     *功能描述  被观察者-----------具体目标 人民日报是具体目标
     */
    class PeopleDaily extends WeChatSubscribe {
    
        @Override
        public void notifyObserver() {
            System.out.println("具体目标发生改变...");
            System.out.println("人民日报发送了房价上涨的消息...");
            System.out.println("--------------");
            for (AbstractUser users : observers) {
                users.response();
            }
        }
    }
    View Code

    结果如下

    例子2 

        用户收到微信服务号的推送消息,若取消关注就收不到推送

    被观察者 微信公众号

    观察者   用户

    public class ObserverPatternTest2 {
    
        public static void main(String[] args) {
            WechatServer server = new WechatServer();
    
            Observer userZhang = new User("ZhangSan");
            Observer userLi = new User("LiSi");
            Observer userWang = new User("WangWu");
    
            server.registerObserver(userZhang);
            server.registerObserver(userLi);
            server.registerObserver(userWang);
            server.setInfomation("第一次推送!");
    
            System.out.println("----------------------------------------------");
            server.removeObserver(userZhang);
            server.setInfomation("第二次推送!");
    
        }
    }
    
    
    
    /**
     *功能描述  观察者接口
     */
    interface Observer {
        /**
         *
         */
        public void update(String message);
    }
    
    /**
     * 功能描述  观察者接口子类
     */
    class User implements Observer {
    
        private String name;
        private String message;
    
        public User(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String message) {
            this.message = message;
            read();
        }
    
        public void read() {
            System.out.println(name + " 收到推送消息: " + message);
        }
    
    }
    
    /**
     * 功能描述  被观察者接口
     */
    interface Observerable {
    
        /**
         * 注册观察者
         */
        public void registerObserver(Observer o);
    
        /**
         * 删除观察者
         */
        public void removeObserver(Observer o);
    
        /**
         * 通知观察者
         */
        public void notifyObserver();
    
    }
    
    /**
     * 功能描述  被观察者子类
     */
    class WechatServer implements Observerable {
    
        /***
         * 注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
         */
        private List<Observer> list;
        private String message;
    
        public WechatServer() {
            list = new ArrayList<Observer>();
        }
    
        @Override
        public void registerObserver(Observer o) {
            list.add(o);
        }
    
        @Override
        public void removeObserver(Observer o) {
            if (!list.isEmpty()) {
                list.remove(o);
            }
        }
    
        @Override
        public void notifyObserver() {
            for (int i = 0; i < list.size(); i++) {
                Observer oserver = list.get(i);
                oserver.update(message);
            }
        }
    
        public void setInfomation(String s) {
            this.message = s;
            System.out.println("微信服务更新消息: " + s);
            //消息更新,通知所有观察者
            notifyObserver();
        }
    
    }
    View Code

    结果如下

    例子3

        多方和空方收到原油期货上涨下跌不同反应

    被观察者 原油期货

    观察者  多方和空方

    public class CrudeOilFutures {
        public static void main(String[] args) {
            OilFutures oil = new OilFutures();
            //多方
            Observer bull = new Bull();
            //空方
            Observer bear = new Bear();
            oil.addObserver(bull);
            oil.addObserver(bear);
            oil.setPrice(10);
            oil.setPrice(-8);
        }
    }
    
    /***
     *功能描述   被观察者----具体目标类:原油期货
     */
    class OilFutures extends Observable {
        private float price;
        public float getPrice() {
            return this.price;
        }
        public void setPrice(float price) {
            //设置内部标志位,注明数据发生变化
            super.setChanged();
            //通知观察者价格改变了
            super.notifyObservers(price);
            this.price = price;
        }
    }
    
    /***
     *功能描述   观察者----具体观察者类:多方
     */
    class Bull implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            Float price = ((Float) arg).floatValue();
            if (price > 0) {
                System.out.println("油价上涨" + price + "元,多方高兴了!");
            } else {
                System.out.println("油价下跌" + (-price) + "元,多方伤心了!");
            }
        }
    }
    
    /***
     *功能描述   观察者----具体观察者类:空方
     */
    class Bear implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            Float price = ((Float) arg).floatValue();
            if (price > 0) {
                System.out.println("油价上涨" + price + "元,空方伤心了!");
            } else {
                System.out.println("油价下跌" + (-price) + "元,空方高兴了!");
            }
        }
    }
    View Code

    结果如下

    古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。
  • 相关阅读:
    巧用border效果
    移动端页面无刷新跳转方法有三种
    word-break和word-wrap的使用和区别
    动态获取移动端视宽,从而结合rem达到适配
    一步一步学习IdentityServer4 (3)自定登录界面并实现业务登录操作
    一步一步学习IdentityServer3 (15) 授权模式那些事
    一步一步学习IdentityServer4 (2) 开始一个简单的事例
    一步一步学习IdentityServer4 (1) 概要配置说明
    Owin 自定义中间件(2)中间件进阶
    一步一步学习IdentityServer3 (14) 启用Https
  • 原文地址:https://www.cnblogs.com/wf-zhang/p/14939594.html
Copyright © 2011-2022 走看看