设计模式-观察者模式

设计模式-观察者模式


概念

  观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。

优点

 1、观察者和被观察者是抽象耦合的。符合依赖倒转原则
 2、建立一套触发机制。

缺点

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

角色

Subject:(主题/通知者)

Observer :(观察者)


使用场景

 1、有多个子类共有的方法,且逻辑相同。 
2、重要的、复杂的方法,可以考虑作为模板方法。

Demo描述

   本次使用观察者模式实现一个关于家电(观察者)观察家电智能控制系统(主题/通知者),家电智能控制系统能感知主人是否入睡和起床,将感知的变化通知给加入家电智能控制系统的家电

UML类图


代码解析UML类图

Subject:(主题/通知者)抽象类
/**
 * 设计模式-观察者模式-抽象主题/通知者
 *
 * 主题是什么?
 * 主题就是被观察者所关心的焦点
 *
 * 抽象智能家电控制系统
 * Created by laizhiyuan on 2017/6/8.
 */
public abstract class AbstractSmartControllerSystemSubject {

    /**
     * 将所有观察者放到一个集合中
     */
    private List<AbstractHomeApplianceObserver> observers
            = new ArrayList<AbstractHomeApplianceObserver>();

    /**
     * 添加一个观察者
     *
     * 假设买回一个家电,就将家电的智能Id号输入到智能家电控制系统中
     * @param observer
     */
    public void addObserver(AbstractHomeApplianceObserver observer){
        observers.add(observer);
    }

    /**
     * 删除一个观察者
     *
     * @param observer
     */
    public void delObserver(AbstractHomeApplianceObserver observer){
        observers.remove(observer);
    }


    /**
     * 通知所有观察者
     */
    public void Notify(){

        for (AbstractHomeApplianceObserver observer : observers){
            observer.update();
        }
    }

    /**
     * 具体主题的状态
     *
     * 可以想象成智能家电控制系统可以感知到主人是否入睡和是否起床
     * 并随之改变状态
     */
    private String state;

    public String getState() {

        return state;
    }


    public void setState(String state) {

        this.state = state;
        /**
         * 按需求走,这个方法可以给客户端自己调用,不在这里调用
         *
         * 我这里是直接再状态改变后就同时调用通知方法
         */
        Notify();
    }
}
Subject:(主题/通知者)具体实现类

/**
 * 设计模式-观察者模式-具体主题
 *
 * 具体智能家电控制系统
 * Created by laizhiyuan on 2017/6/8.
 */
public class SmartControllerSystemConcreteSubject extends AbstractSmartControllerSystemSubject{


}

Observer :(观察者)抽象类
/**
 * 设计模式-观察者模式-抽象观察者
 *
 * 观察者是什么?
 * 观察者就是观察某个主题是否发生变化
 *
 * 这里实现的观察者指的是家电如:电灯,空调,饮水机等,
 *   它们观察智能家电控制系统是否发出主人已经睡觉或者起床的信息
 *
 * 抽象家电观察者,主要观察的是智能家电控制系统这个主题
 * Created by laizhiyuan on 2017/6/8.
 */
public abstract class AbstractHomeApplianceObserver {

    /**
     * 家电名称
     */
    private String homeApplianceName;

    /**
     * 依赖抽象,降低耦合,符号依赖倒转原则
     *
     * 观察的主题,依赖主题的原因是需要从主题中获得主题的状态是什么
     */
    protected AbstractSmartControllerSystemSubject subject;

    /**
     * 实例化时强制入参
     *
     * @param subject
     * @param homeApplianceName
     */
    public AbstractHomeApplianceObserver(AbstractSmartControllerSystemSubject subject, String homeApplianceName) {

        this.homeApplianceName = homeApplianceName;
        this.subject = subject;
    }

    public String getHomeApplianceName() {
        return homeApplianceName;
    }

    public void setHomeApplianceName(String homeApplianceName) {
        this.homeApplianceName = homeApplianceName;
    }

    public AbstractSmartControllerSystemSubject getSubject() {
        return subject;
    }

    public void setSubject(AbstractSmartControllerSystemSubject subject) {
        this.subject = subject;
    }

    /**
     * 得到主题(智能系统)的通知时,更新自己。具体家电去实现,
     */
    public abstract void update();
}


Observer :(观察者)具体实现类

/**
 * 设计模式-观察者模式-具体观察者
 *
 * 电灯
 *
 * Created by laizhiyuan on 2017/6/8.
 */
public class TheLightConcreteObserver extends AbstractHomeApplianceObserver{


    /**
     * 实例化时强制入参
     *
     * @param subject
     * @param homeApplianceName
     */
    public TheLightConcreteObserver(AbstractSmartControllerSystemSubject subject, String homeApplianceName) {

        super(subject, homeApplianceName);
    }


    @Override
    public void update() {
        if (subject.getState().equals("sleep")){

            System.out.println("主人已睡觉,关灯!");
        }else if (subject.getState().equals("getUp")){

            /**
             * 假设未来非常热(50摄氏度)很多人都住地下室,比较凉快
             * 现在天气越来越热,多年后达到50摄氏度不是夸张
             *
             * 白天是需要开灯的
             */
            System.out.println("主人已起床,开灯!");
        }
    }
}

/**
 * 设计模式-观察者模式-具体观察者
 *
 * 饮水机
 *
 * Created by laizhiyuan on 2017/6/8.
 */
public class WaterDispenserConcreteObserver extends AbstractHomeApplianceObserver{


    /**
     * 实例化时强制入参
     *
     * @param subject
     * @param homeApplianceName
     */
    public WaterDispenserConcreteObserver(AbstractSmartControllerSystemSubject subject, String homeApplianceName) {
        super(subject, homeApplianceName);
    }

    @Override
    public void update() {
        if (subject.getState().equals("sleep")){

            System.out.printf("主人已睡,饮水机关电!");
        }else if (subject.getState().equals("getUp")){

            System.out.println("主人起床,饮水机开电");
        }
    }
}

测试

/**
 * main方法测试
 *
 * Created by laizhiyuan on 2017/6/8.
 */
public class Main {

    public static void main(String[] args) {

        /**
         * 主题
         *
         * 智能家电控制器
         */
        AbstractSmartControllerSystemSubject subject =
                new SmartControllerSystemConcreteSubject();

        AbstractHomeApplianceObserver observer =
                new TheLightConcreteObserver(subject, "LED电灯");

        AbstractHomeApplianceObserver observer1 =
                new WaterDispenserConcreteObserver(subject, "TCL饮水机");

        subject.addObserver(observer);
        subject.addObserver(observer1);

        /**
         * 当智能系统控制器感知到主人已入睡,改变状态为sleep
         */
        subject.setState("sleep");

        try {

            System.out.println("\n 睡眠中......");
            /**
             * 模拟睡觉8小时
             */
            Thread.sleep(5000);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /**
         * 当智能系统控制器感知到主人已起床,改变状态为getUp
         */
        subject.setState("getUp");

    }
}

控制台输出


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值