(10)设计模式之观察者模式

观察者模式

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


观察者模式UML类图
在这里插入图片描述
其中Subject是抽象的主题类,也叫做抽象的通知者类。
Observer是抽象的观察者类。
Concrete分别是具体的实现。

比如这样一个情景,公司里老板不在,小王小张小李都在摸鱼,可是老板突然回来了,前台首先发现了老板回来了,那么他需要通知公司的员工停止摸鱼,继续工作。这时前台做的就是具体的通知者类。但是如果前台没来得及通知同事们,老板就已经看到了同事们在摸鱼,这时具体的通知者就是老板自己。

以通知者是老板自己为例,代码如下:

package sjms.observer;

public interface Observer {//抽象的同事类(观察者类)
    public void Update();
}
package sjms.observer;

import java.util.ArrayList;
import java.util.List;

public abstract class Subject {//抽象的通知者类
    private List<Observer> observers = new ArrayList<Observer>();
    //增加观察者
    public void Attach(Observer observer){
        observers.add(observer);
    }
    //移除观察者
    public void Detach(Observer observer){
        observers.remove(observer);
    }
    public void Notify(){
    //使用遍历的方法,对添加进来的同事(观察者)进行通知,并作出相应的状态的改变
        for (Observer observer : observers) {
            observer.Update();
        }
    }
}
package sjms.observer;

public class ConcreteSubject extends Subject{
//具体的通知者类
    private String subjectState;
    //具体被观察者状态

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }
}
package sjms.observer;

public class ConcreteObserver implements Observer{
//简便期间,只写了一个具体的观察者类(同事类)
    private String name;
    private String observeState;
    private ConcreteSubject subject;

    public ConcreteObserver(ConcreteSubject subject,String name){
        this.subject=subject;
        this.name=name;
    }
    @Override
    public void Update() {
        observeState=subject.getSubjectState();
        //通知被观察者的状态发生了哪种改变, 让相应的观察者作出相应的改变。
        System.out.println(observeState+name+",停止摸鱼,抓紧工作!");
    }

    public ConcreteSubject getSubject() {
        return subject;
    }

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

package sjms.observer;
//客户端
public class client {
    public static void main(String[] args) {
        ConcreteSubject s = new ConcreteSubject();

        s.Attach(new ConcreteObserver(s,"小王"));
        s.Attach(new ConcreteObserver(s,"小张"));
        s.Attach(new ConcreteObserver(s,"小李"));
        s.setSubjectState("停止摸鱼,抓紧工作!");
        s.Notify();

    }
}

运行结果:

老板我回来了!小王,停止摸鱼,抓紧工作!
老板我回来了!小张,停止摸鱼,抓紧工作!
老板我回来了!小李,停止摸鱼,抓紧工作!

使用观察者模式的动机是什么?
将一个系统分割成一系列相互写作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。

什么时候应该使用观察者模式?

  1. 当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待改变时,应该考虑观察者模式。比如当电脑打开开机键的时候,电脑的CPU、显示屏、GPU等维持电脑运行的部件都会一起开始运行。
  2. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面,这时使用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
  3. 总的来说,观察者模式所做的工作其实就是在解除耦合。让耦合双方都依赖于抽象,而不是依赖于具体。从而使得各自地变化都不会影响另一边的变化。这就是依赖倒转原则的最佳体现。

特点:
观察者和目标的抽象耦合。
实现了动态联动。
支持广播通信。
但是可能引起无谓操作。

观察者模式还可以使用委托使抽象的观察者和抽象的通知者进行解耦处理,委托可以实现调用不同函数。


一个例子:
有两支股票,在股票发生变化时,分别对购买相应的股票的人进行通知。

UML类图:
在这里插入图片描述

package ch10.sjms.invest;

public interface Investor {
    public void Update();
}
package ch10.sjms.invest;

import java.util.ArrayList;
import java.util.List;

public class Stock {
    private List<Investor> investors = new ArrayList<Investor>();
    public void Attach(Investor investor){
        investors.add(investor);
    }
    public void Detach(Investor investor){
        investors.remove(investor);
    }
    public void Notify(){
        for (Investor investor : investors) {
            investor.Update();
        }
    }
}
package ch10.sjms.invest;

public class ConcreteStock extends Stock{
    private String StockState;

    public String getStockState() {
        return StockState;
    }

    public void setStockState(String stockState) {
        StockState = stockState;
    }
}
package ch10.sjms.invest;

public class ConcreteStockB extends Stock{
    private String StockState;

    public String getStockState() {
        return StockState;
    }

    public void setStockState(String stockState) {
        StockState = stockState;
    }
}
package ch10.sjms.invest;

public class ConcreteInvestor implements Investor {
    private String name;
    private String StockState;
    private ConcreteStock stock;
    public ConcreteInvestor(ConcreteStock stock,String name){
        this.stock=stock;
        this.name=name;
    }
    @Override
    public void Update() {
        StockState = stock.getStockState();
        System.out.println("投资者"+name+"的A股票"+StockState);
    }

    public ConcreteStock getStock() {
        return stock;
    }

    public void setStock(ConcreteStock stock) {
        this.stock = stock;
    }
}
package ch10.sjms.invest;

public class ConcreteInvestorB implements Investor {
    private String name;
    private String StockState;
    private ConcreteStockB stock;
    public ConcreteInvestorB(ConcreteStockB stock, String name){
        this.stock=stock;
        this.name=name;
    }
    @Override
    public void Update() {
        StockState = stock.getStockState();
        System.out.println("投资者"+name+"的B股票"+StockState);
    }

    public ConcreteStockB getStock() {
        return stock;
    }

    public void setStock(ConcreteStockB stock) {
        this.stock = stock;
    }
}
package ch10.sjms.invest;

public class client {
    public static void main(String[] args) {
        ConcreteStock s = new ConcreteStock();
        s.Attach(new ConcreteInvestor(s,"张三"));
        s.Attach(new ConcreteInvestor(s,"李四"));

        s.setStockState("涨了");
        s.Notify();

        ConcreteStockB s1=new ConcreteStockB();
        s1.Attach(new ConcreteInvestorB(s1,"王五"));

        s1.setStockState("跌了");
        s1.Notify();
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值