logo头像
ICQL

designpattern_行为型

行为型设计模式概述

用来描述一些常用行为的设计模式



观察者模式

定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅模式

观察者模式和生产消费者模型的区别:

观察者:一对多,订阅者不存在竞争关系
生产者消费者:多对多,一般消费者之间存在竞争关系,只会有一个消费者可以收到消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* 具体被观察者
*/
public class ConcreteObservable extends Observable {

public void sendMsg(String msg) {
setChanged();
notifyObservers(msg);
}
}

/**
* 具体的观察者1
*/
public class ConcreteObserver1 implements Observer {

@Override
public void update(Observable o, Object arg) {
System.out.println("观察者1-收到消息:" + arg);
}
}

/**
* 具体的观察者2
*/
public class ConcreteObserver2 implements Observer {

@Override
public void update(Observable o, Object arg) {
System.out.println("观察者2-收到消息:" + arg);
}
}

/**
* 观察者模式
*/
public class ObserverClient {

public static void main(String[] args) {
//java提供了Observer接口和Observable类来作为观察者模式的抽象层
//我们只需要自定义具体观察者类和具体观察目标类即可实现观察者模式
ConcreteObservable observable = new ConcreteObservable();
observable.addObserver(new ConcreteObserver1());
observable.addObserver(new ConcreteObserver2());
observable.sendMsg("测试消息");
}
}


模板模式

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤

作用:

(1)复用
java-io中 InputStream,OutputStream,Reader,Writer等,InputStream 的 read 方法
Java AbstractList,addAll(int index, Collection<? extends E> c) 方法 -> add(int index, E element)
(2)扩展
HttpServlet中的service()方法是一个模板方法,它实现了整个 HTTP 请求的执行流程,doGet()、doPost() 是模板中可以由子类来定制的部分

回调机制:同步回调(和模板方法模式作用相似),异步回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public abstract class AbstractClass {

public final void templateMethod() {
//...
method1();
//...
method2();
//...
}

protected abstract void method1();

protected abstract void method2();
}

public class ConcreteClass1 extends AbstractClass {

@Override
protected void method1() {
System.out.println("ConcreteClass1.method1");
}

@Override
protected void method2() {
System.out.println("ConcreteClass1.method2");
}
}

public class ConcreteClass2 extends AbstractClass {

@Override
protected void method1() {
System.out.println("ConcreteClass2.method1");
}

@Override
protected void method2() {
System.out.println("ConcreteClass2.method2");
}
}

/**
* 模板方法模式
*/
public class TemplateClient {

public static void main(String[] args) {
AbstractClass demo1 = new ConcreteClass1();
demo1.templateMethod();

AbstractClass demo2 = new ConcreteClass2();
demo2.templateMethod();
}
}


策略模式

定义一组算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端

场景:

使用策略模式一般借助工厂模式封装策略
取消if else分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
* 策略接口定义
*/
public interface Strategy {

void operation();
}

/**
* 具体的策略A
*/
public class ConcreteStrategyA implements Strategy {

@Override
public void operation() {
System.out.println("具体的策略A");
}
}

/**
* 具体的策略B
*/
public class ConcreteStrategyB implements Strategy {

@Override
public void operation() {
System.out.println("具体的策略B");
}
}

/**
* 策略使用工厂
*/
public class StrategyFactory {

private static final Map<String, Strategy> STRATEGY_BY_TYPE = new HashMap<>();

static {
STRATEGY_BY_TYPE.put("A", new ConcreteStrategyA());
STRATEGY_BY_TYPE.put("B", new ConcreteStrategyB());
}

public Strategy getStrategy(String type) {
//校验type
return STRATEGY_BY_TYPE.get(type);
}
}

public class StrategyClient {

public static void main(String[] args) {
StrategyFactory factory = new StrategyFactory();
Strategy strategyA = factory.getStrategy("A");
strategyA.operation();
}
}


职责链模式

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止

经典应用:Servlet Filter,Spring Interceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//(1)数组实现
public interface IHandler {

boolean handle(Object o);
}

public class HandlerA implements IHandler {

@Override
public boolean handle(Object o) {
boolean handled = false;
//...
return handled;
}
}

public class HandlerB implements IHandler {

@Override
public boolean handle(Object o) {
boolean handled = false;
//...
return handled;
}
}

public class HandlerChain {

private List<IHandler> handlers = new ArrayList<>();

public void addHandler(IHandler handler) {
this.handlers.add(handler);
}

public void handle(Object o) {
for (IHandler handler : handlers) {
boolean handled = handler.handle(o);
if (handled) {
break;
}
}
}
}

//(2)链表实现
public abstract class Handler {

protected Handler successor = null;

public void setSuccessor(Handler successor) {
this.successor = successor;
}

public final void handle(Object o) {
boolean handled = doHandle(o);
if (successor != null && !handled) {
successor.handle(o);
}
}

protected abstract boolean doHandle(Object o);
}

public class HandlerA extends Handler {

@Override
protected boolean doHandle(Object o) {
boolean handled = false;
//...
return handled;
}
}

public class HandlerB extends Handler {

@Override
protected boolean doHandle(Object o) {
boolean handled = false;
//...
return handled;
}
}

public class HandlerChain {

private Handler head = null;
private Handler tail = null;

public void addHandler(Handler handler) {
handler.setSuccessor(null);
if (head == null) {
head = handler;
tail = handler;
return;
}
tail.setSuccessor(handler);
tail = handler;
}

public void handle(Object o) {
if (head != null) {
head.handle(o);
}
}
}

/**
* 职责链模式
* 2种实现方式:链表和数组,数组相对简单易用
*/
public class ChainOfResponsibilityClient {

public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.handle(new Object());
}
}


状态模式

状态机(有限状态机)的常用表示法有 分支判断,查表,状态模式



迭代器模式

  • 迭代器是用来遍历容器,编程语言一般都已经实现好了
  • 正常情况下,迭代器遍历中为什么不能添加和删除元素?(jdk中在iterator内部类中维护了一个字段lastRet用以解决此问题)
    • 当添加/删除的元素在迭代器游标的前面就会出现问题
    • 当添加/删除的元素在迭代器游标的后面不会出现问题


访问者模式

  • 允许一个或者多个操作应用到一组对象上,解耦操作和对象本身


备忘录模式

  • 备忘录模式,也叫快照(Snapshot)模式,存储副本以便后期恢复


命令模式

  • 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
  • 和策略模式的实现形式很相似,区别:
    • 策略模式是通过不同的算法做同一件事情:例如排序,而命令模式则是通过不同的命令做不同的事情,常含有接收者,如菜单中的复制,移动,压缩


解释器模式

  • 解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法


中介模式

  • 中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互
微信打赏

赞赏是不耍流氓的鼓励