设计模式(三)行为型

发布时间 2023-05-25 12:25:54作者: coooooookie

1、策略模式

和桥梁模式很相似,但桥梁模式的耦合更低,结构更复杂一些。

 2、观察者模式

观察者模式是一种行为型设计模式,当一个对象发生改变时,所有依赖它的对象都会得到通知并自动更新。这种模式也被称为发布-订阅模式或者消息机制。

观察者模式包含以下几个角色:

  1. Subject(主题):被观察的对象,它维护了所有观察者对象的列表,并提供了添加和删除观察者的方法,以及通知观察者的方法。

  2. Observer(观察者):观察主题的对象,当主题状态改变时,观察者接收到通知并进行相应的操作。

  3. ConcreteSubject(具体主题):实现了主题接口的对象,它维护了一个状态,并在状态发生改变时通知所有的观察者。

  4. ConcreteObserver(具体观察者):实现了观察者接口的对象,它存储了一个指向具体主题对象的引用,并能够接收具体主题发出的通知。

观察者模式常用于需要实现松耦合的场景,例如事件驱动系统、GUI系统中的事件监听等。它可以让对象之间的耦合度更低,并且允许动态地添加或删除观察者,从而提高系统的灵活性和扩展性。

 1 首先,需要定义主题,每个主题需要持有观察者列表的引用,用于在数据变更的时候通知各个观察者:
 2 public class Subject {
 3     private List<Observer> observers = new ArrayList<Observer>();
 4     private int state;
 5     public int getState() {
 6         return state;
 7     }
 8     public void setState(int state) {
 9         this.state = state;
10         // 数据已变更,通知观察者们
11         notifyAllObservers();
12     }
13     // 注册观察者
14     public void attach(Observer observer) {
15         observers.add(observer);
16     }
17     // 通知观察者们
18     public void notifyAllObservers() {
19         for (Observer observer : observers) {
20             observer.update();
21         }
22     }
23 }
24 
25 定义观察者接口:
26 public abstract class Observer {
27     protected Subject subject;
28     public abstract void update();
29 }
30 
31 其实如果只有一个观察者类的话,接口都不用定义了,不过,通常场景下,既然用到了观察者模式,我们就是希望一个事件出来了,会有多个不同的类需要处理相应的信息。比如,订单修改成功事件,我们希望发短信的类得到通知、发邮件的类得到通知、处理物流信息的类得到通知等。
32 
33 我们来定义具体的几个观察者类:
34 public class BinaryObserver extends Observer {
35     // 在构造方法中进行订阅主题
36     public BinaryObserver(Subject subject) {
37         this.subject = subject;
38         // 通常在构造方法中将 this 发布出去的操作一定要小心
39         this.subject.attach(this);
40     }
41     // 该方法由主题类在数据变更的时候进行调用
42     @Override
43     public void update() {
44         String result = Integer.toBinaryString(subject.getState());
45         System.out.println("订阅的数据发生变化,新的数据处理为二进制值为:" + result);
46     }
47 }
48 
49 public class HexaObserver extends Observer {
50     public HexaObserver(Subject subject) {
51         this.subject = subject;
52         this.subject.attach(this);
53     }
54     @Override
55     public void update() {
56         String result = Integer.toHexString(subject.getState()).toUpperCase();
57         System.out.println("订阅的数据发生变化,新的数据处理为十六进制值为:" + result);
58     }
59 }
60 
61 客户端使用也非常简单:
62 public static void main(String[] args) {
63     // 先定义一个主题
64     Subject subject1 = new Subject();
65     // 定义观察者
66     new BinaryObserver(subject1);
67     new HexaObserver(subject1);
68 
69     // 模拟数据变更,这个时候,观察者们的 update 方法将会被调用
70     subject.setState(11);
71 }
View Code

3、模板方法模式

在含有继承结构的代码中,模板方法模式是非常常用的。模板方法中调用了 3 个方法,其中 apply() 是抽象方法,子类必须实现它,其实模板方法中有几个抽象方法完全是自由的,我们也可以将三个方法都设置为抽象方法,让子类来实现。也就是说,模板方法只负责定义第一步应该要做什么,第二步应该做什么,第三步应该做什么,至于怎么做,由子类来实现。

public abstract class AbstractTemplate {
    // 这就是模板方法
    public void templateMethod() {
        init();
        apply(); // 这个是重点
        end(); // 可以作为钩子方法
    }

    protected void init() {
        System.out.println("init 抽象层已经实现,子类也可以选择覆写");
    }

    // 留给子类实现
    protected abstract void apply();

    protected void end() {
    }
}