java 设计模式之观察者模式(十六)

115 阅读3分钟

java 设计模式之观察者模式①⑥

二十岁之后就不应该与人争论,人对自己的观念都非常固执,不要企图能说服别人。

设计模式学习,近期我会把23中设计模式都写成博客,敬请期待~
—2021/1/21

定义

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

百度百科

项目需求分析

假设我现在想喝牛奶,或者红牛,我就得去商店购买

在这里,商店就是’被观察者’,购买的商品就是’观察者’

在商店中你可以选择购买,也可以选择不够买,最终确定之后输出选择的商品,

无论最后选择多少商品,都是在同一家超市’结账’(输出).

在代码中也是一样的,你可以订阅多个观察者,但是观察者只能有一个.

在这个例子中表示你可以选各种商品,但必须在这家商店中结账.

代码来源于生活

角色分析

UML类图分析(1.1):
在这里插入图片描述

  • Subject: 抽象主题(被观察者) :抽象主题提供一个接口,可以增加和删除观察者对象。
  • SubjectImpl: 抽象主题实现(被观察者实现) :将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  • Observer:抽象观察者 :为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • MilkObserverImpl / RedBullObserver :抽象观察者实现 : 实现抽象观察者角色所要求的更新接口

代码实现

Subject被观察者 这里指商店(用来添加 / 移除 / 输出 商品):

public interface Subject {

    /**
     *    移除观察者
     */
    public void removeObserver(Observer observer);


    /**
     *    注册观察者
     */
    public void registerObserver(Observer observer);

    /**
     *   刷新观察者
     */
    public void notfiyObservers();
}

Observer观察者(具体商品规范):

public interface Observer {
    public void update();
}

MilkObserverImpl 牛奶商品实现:

public class MilkObserverImpl implements Observer{

    String food;
    public MilkObserverImpl(String food) {
        this.food = food;
    }
    @Override
    public void update() {
        Log.i("观察者模式","饮料为:  "+food);
    }
}

RedBullObserverImpl 红牛商品实现:

public class RedBullObserverImpl implements Observer{

    String food;

    public RedBullObserverImpl(String food) {
        this.food = food;
    }

    @Override
    public void update() {
        Log.i("观察者模式","饮料为:  "+food);
    }
}

SubjectImpl 添加 / 移除 / 输出最终商品:

public class SubjectImpl implements Subject{
    List<Observer> list = new ArrayList<>();

    @Override
    public void removeObserver(Observer observer) {
        //判断是否有当前状态
        if (list.contains(observer)) {
            list.remove(observer);
        }
    }

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void notfiyObservers() {
        for (int i = 0; i < list.size(); i++) {
            list.get(i).update();
        }
    }
}

测试代码(客户端):

//观察者
        SubjectImpl subject = new SubjectImpl();

        //被观察者
        MilkObserverImpl milkObserver = new MilkObserverImpl("牛奶");
        RedBullObserverImpl redBullObserver = new RedBullObserverImpl("红牛");

        //注册牛奶观察者
        subject.registerObserver(milkObserver);

        //注册红牛观察者
        subject.registerObserver(redBullObserver);

        //刷新 (输出结果)
        subject.notfiyObservers();

Log图(2.1):
在这里插入图片描述

移除商品代码:

 //观察者
        SubjectImpl subject = new SubjectImpl();

        //被观察者
        MilkObserverImpl milkObserver = new MilkObserverImpl("牛奶");
        RedBullObserverImpl redBullObserver = new RedBullObserverImpl("红牛");

        //注册牛奶观察者
        subject.registerObserver(milkObserver);

        //注册红牛观察者
        subject.registerObserver(redBullObserver);


        //刷新 (输出结果)
        subject.notfiyObservers();
        Log.i("观察者模式"," ======= 移除商品,重新输出 ============");
        //移除红牛观察者
        subject.removeObserver(redBullObserver);


        //刷新 (输出结果)
        subject.notfiyObservers();

Log图(2.2):
在这里插入图片描述

如何扩展商品

CocaColaObserverImpl 新扩展可口可乐商品:

public class CocaColaObserverImpl implements Observer{

    String food;

    public CocaColaObserverImpl(String food) {
        this.food = food;
    }

    @Override
    public void update() {
        Log.i("观察者模式","饮料为:  "+food);
    }
}

测试代码:

		....
        CocaColaObserverImpl colaObserver = new CocaColaObserverImpl("可口可乐");
		.....

        Log.i("观察者模式"," ======= 新商品,重新输出 ============");
        subject.registerObserver(colaObserver);

        subject.notfiyObservers();

Log图(2.3):
在这里插入图片描述

完整代码

去设计模式/设计原则主页

原创不易,您的点赞就是对我最大的支持~