设计模式

设计模式是为了让程序具有更好的可读性、可靠性、可扩展性、代码重用性,使程序呈现高内聚、低耦合的特性。

软件设计原则

  • 单一职责原则:一个类只负责一项职责(并不是一个方法),如果逻辑简单,类中方法少,可以在方法级别保持单一职责原则。
  • 接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上。
  • 开闭原则:它是最基础,最重要的设计原则。软件模块方法和函数应该对扩展(提供方)开放对修改(使用方)关闭,用抽象构建框架,用实现扩展细节。
  • 里氏替换原则:所有引用基类的地方必须能透明地使用其子类对象,尽量少使用继承,采用依赖,聚合,组合等关系代替。
  • 依赖倒转原则:底层模块尽量有抽象类或接口,或者两个都有。变量的声明类型尽量是抽象类或接口。
  • 迪米特法则:核心是降低类之间的耦合,对自己依赖的类知道的越少越好。
  • 合成复用原则:尽量使用合成/聚合的方式,不使用继承。

类的关系与UML类图

  • 依赖(虚线加箭头)
  • 关联(实线加箭头)
  • 实现(虚线加三角形)
  • 泛化/继承(实线加三角形)
  • 聚合(实线加实心菱形)
  • 组合(实线加空心菱形)

创建者模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

饿汉式(静态常量)

  • 私有化构造器
  • 在类的内部创建一个静态常量的对象实例
  • 提供一个静态的共有方法获取实例
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
/**
* 单例模式:饿汉式(静态常量)
* 优点:写法简单,避免线程同步
* 缺点:不用的话,会造成内存浪费
* 总结:如果确定使用该类的话推荐使用
*/
public class Singleton {
//构造器私有,外部不能根据构造器创建对象
private Singleton() {}

//在类的内部创建一个对象实例
private static final Singleton instance = new Singleton();

//提供一个公有的静态方法返回该类的实例对象
public static Singleton getInstance() {
return instance;
}
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

懒汉式(线程不安全)

  • 私有化构造器
  • 在类的内部定义一个静态对象
  • 提供一个静态的公有方法
  • 判断对象为空则创建对象返回,对象不为空则直接返回
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
/**
* 单例模式:懒汉式
* 优点:使用时创建,不会造成内存浪费
* 缺点:线程不安全
* 总结:不推荐使用
*/
public class Singleton {
//构造器私有,外部不能根据构造器创建对象
private Singleton(){}

private static Singleton instance = null;

//提供一个静态的公有方法,当使用该方法时再创建该对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

懒汉式(同步方法,线程安全)

  • 私有化构造器
  • 在类的内部定义一个静态对象
  • 提供一个静态的公有方法(方法加同步锁)
  • 判断对象为空则创建对象并返回,对象不为空则直接返回
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
/**
* 单例模式:懒汉式
* 优点:使用时创建,不会造成内存浪费,同步方法,线程安全
* 缺点:效率低
* 总结:不推荐使用
*/
public class Singleton {
//构造器私有,外部不能根据构造器创建对象
private Singleton(){}

private static Singleton instance = null;

//提供一个静态的公有方法,当时用该方法时再创建该对象
//加入synchronized,解决线程安全问题
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

懒汉式(双重校检锁)

  • 私有化构造器
  • 在类的内部定义一个静态对象
  • 提供一个静态的公有方法
  • 判断对象是否为空,不为空直接返回
  • 对象为空,添加同步锁->再次判断对象是否为空
  • 对象为空则创建对象并返回,对象不为空则直接返回
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
/**
* 单例模式:双重校检锁
* 优点:使用时创建,不会造成内存浪费,同步方法,线程安全
* 总结:推荐使用
*/
public class Singleton {
//构造器私有,外部不能根据构造器创建对象
private Singleton(){}

private static volatile Singleton instance = null;

//提供一个静态的公有方法,当时用该方法时再创建该对象
//加入双重检查代码,解决线程安全问题,解决效率的问题
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

懒汉式(静态内部类)

  • 私有化构造器
  • 在类的内部创建一个私有的静态类,类中有一个静态常量的对象实例
  • 在外部类中,提供一个共有的静态方法,调用该方法时返回静态内部类中的对象实例
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
/**
* 单例模式:静态内部类
* 优点:静态内部类在Singleton类装载时不会实例化,调用getInstance方法时再会装载SingletonInstance类,
* JVM装载SingletonInstance类时,别的线程无法进入,保证了线程安全
* 利用静态内部类特点实现延迟加载,效率高
* 总结:推荐使用
*/
public class Singleton {
//构造器私有,外部不能根据构造器创建对象
private Singleton(){}

//创建一个静态内部类,该类中有一个静态属性singleton
private static class SingletonInstance {
private static final Singleton INSTANCE = new Singleton();
}

//提供一个静态的公有方法,当时用该方法时再创建该对象
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

枚举类

  • 枚举类本身就有单例的特性,初始化时线程安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 单例模式:枚举
* 优点: JDK1.5 之后才加入 enum 特性 是它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
* 总结:推荐使用
*/
enum Singleton {
INSTANCE;
}

public class Test {
public static void main(String[] args) {
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());
}
}

原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

浅拷贝

  • 类继承Cloneable接口
  • 实现clone方法
  • 使用clone方法克隆出一个新的对象
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
public class Sheep implements Cloneable {

private String name;

private int age;

private Sheep friend;

public Sheep(String name, int age, Sheep friend) {
this.name = name;
this.age = age;
this.friend = friend;
}

public Sheep getFriend() {
return friend;
}

public void setFriend(Sheep friend) {
this.friend = friend;
}

@Override
public String toString() {
return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", friend=" + friend + '}';
}

@Override
public Sheep clone() {
try {
return (Sheep) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}

public class Run {
public static void main(String[] args) {
Sheep harry = new Sheep("Harry", 1, null);
Sheep dolly = new Sheep("Dolly", 1, harry);

System.out.println(dolly.toString());

//克隆羊多莉1号
Sheep clone1 = dolly.clone();
Sheep clone2 = dolly.clone();

System.out.println("多莉1号克隆体:" + clone1.hashCode());
System.out.println("多莉2号克隆体:" + clone1.hashCode());
//可以发现克隆体的对象是不一样的
System.out.println(clone1 == clone2);

System.out.println("多莉1号克隆体朋友:" + clone1.getFriend().hashCode());
System.out.println("多莉2号克隆体朋友:" + clone2.getFriend().hashCode());
//但是内部属性指向的是同一个地址,这是浅拷贝
System.out.println(dolly.getFriend() == clone1.getFriend());
System.out.println(clone1.getFriend() == clone2.getFriend());
}
}

深拷贝

  • 类继承Cloneable接口和Serializable接口
  • 实现clone方法,方法中使用序列化,反序列化返回对象
  • 使用clone方法克隆出一个新的对象
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
public class Sheep implements Cloneable, Serializable {

private String name;

private int age;

private Sheep friend;

public Sheep(String name, int age, Sheep friend) {
this.name = name;
this.age = age;
this.friend = friend;
}

public Sheep getFriend() {
return friend;
}

public void setFriend(Sheep friend) {
this.friend = friend;
}

@Override
public String toString() {
return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", friend=" + friend + '}';
}

@Override
public Sheep clone() {
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
//对象序列化
oos.writeObject(this);

//对象反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return (Sheep) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (bos != null) {bos.close();}
if (oos != null) {oos.close();}
if (bis != null) {bis.close();}
if (ois != null) {ois.close();}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

public class Run {
public static void main(String[] args) {
Sheep harry = new Sheep("Harry", 1, null);
Sheep dolly = new Sheep("Dolly", 1, harry);

System.out.println(dolly.toString());

//克隆羊多莉1号
Sheep clone1 = dolly.clone();
Sheep clone2 = dolly.clone();

System.out.println("多莉1号克隆体:" + clone1.hashCode());
System.out.println("多莉2号克隆体:" + clone1.hashCode());
//可以发现克隆体的对象是不一样的
System.out.println(clone1 == clone2);

System.out.println("多莉1号克隆体朋友:" + clone1.getFriend().hashCode());
System.out.println("多莉2号克隆体朋友:" + clone2.getFriend().hashCode());
//内部属性指向不同的地址,这是深拷贝
System.out.println(dolly.getFriend() == clone1.getFriend());
System.out.println(clone1.getFriend() == clone2.getFriend());
}
}

简单工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

结构

  • 创建一个抽象类/接口
  • 新建几个类,继承/实现
  • 创建一个工厂类,
  • 工厂类中新建一个静态方法,根据不同的值返回相对应类的实例
  • 客户端直接使用工厂类调用静态方法,就可以获取需要的实例
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
public abstract class Color {

public String nameCN;

public String nameEN;

public abstract String getRGBString();

public abstract String getHexadecimalString();

}

public class Black extends Color {

public Black() {
nameCN = "黑色";
nameEN = "black";
}

@Override
public String getRGBString() {
return nameCN + " " + nameEN + " GRB: " + "255,255,255";
}

@Override
public String getHexadecimalString() {
return nameCN + " " + nameEN + " 十六进制: " + "#FFFFFF";
}
}

public class Blue extends Color {

public Blue() {
nameCN = "蓝色";
nameEN = "blue";
}

@Override
public String getRGBString() {
return nameCN + " " + nameEN + " GRB: " + "0,0,255";
}

@Override
public String getHexadecimalString() {
return nameCN + " " + nameEN + " 十六进制: " + "#0000FF";
}
}

public class Red extends Color {

public Red() {
nameCN = "红色";
nameEN = "red";
}

@Override
public String getRGBString() {
return nameCN + " " + nameEN + " GRB: " + "255,69,0";
}

@Override
public String getHexadecimalString() {
return nameCN + " " + nameEN + " 十六进制: " + "#FF0000";
}
}

public class White extends Color {

public White() {
nameCN = "白色";
nameEN = "white";
}

@Override
public String getRGBString() {
return nameCN + " " + nameEN + " GRB: " + "255,255,255";
}

@Override
public String getHexadecimalString() {
return nameCN + " " + nameEN + " 十六进制: " + "#FFFFFF";
}
}

public enum ColorType {
RED, BLUE, BLACK, WHITE
}

//简单工厂模式
public class ColorFactory {
public static Color getColor(ColorType colorType) {
if (colorType == null)
return null;
switch(colorType) {
case RED: return new Red();
case BLUE: return new Blue();
case BLACK: return new Black();
case WHITE: return new White();
default: return null;
}
}
}

public class Run {
public static void main(String[] args) {
ColorType[] values = ColorType.values();
for (ColorType colorType : values) {
Color color = ColorFactory.getColor(colorType);
if (color == null) return;
String rgbString = color.getRGBString();
System.out.println(rgbString);
String hexadecimalString = color.getHexadecimalString();
System.out.println(hexadecimalString);
}
}
}

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
public interface Color {
public void fill();
}

public class Black implements Color {
@Override
public void fill() {
System.out.println("填充黑色");
}
}

public class Blue implements Color {
@Override
public void fill() {
System.out.println("填充蓝色");
}
}

public class Red implements Color {
@Override
public void fill() {
System.out.println("填充红色");
}
}

public class White implements Color {
@Override
public void fill() {
System.out.println("填充白色");
}
}

public enum ColorType {
/**
* 红色
*/
RED,

/**
* 蓝色
*/
BLUE,

/**
* 黑色
*/
BLACK,

/**
* 白色
*/
WHITE
}

public interface Shape {
public void draw();
}

public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆型");
}
}

public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制长方形");
}
}

public class Square implements Shape {
@Override
public void draw() {
System.out.println("绘制正方形");
}
}

public class Triangle implements Shape {
@Override
public void draw() {
System.out.println("绘制三角形");
}
}

public enum ShapeType {
/**
* 圆型
*/
CIRCLE,

/**
* 长方形
*/
RECTANGLE,

/**
* 正方形
*/
SQUARE,

/**
* 三角形
*/
TRIANGLE
}

public abstract class AbstractFactory {
//获取形状
public abstract Shape getShape(ShapeType shapeType);

//获取颜色
public abstract Color getColor(ColorType colorType);
}

public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(ShapeType shapeType) {
return null;
}

@Override
public Color getColor(ColorType colorType) {
if (colorType == null)
return null;
switch (colorType) {
case RED: return new Red();
case BLUE: return new Blue();
case BLACK: return new Black();
case WHITE: return new White();
default: return null;
}
}
}

public class ProducerFactory {
public static AbstractFactory getFactory(FactoryType factoryType) {
if (factoryType == null)
return null;
switch (factoryType) {
case SHAPE: return new ShapeFactory();
case COLOR: return new ColorFactory();
default: return null;
}
}
}

public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(ShapeType shapeType) {
if (shapeType == null)
return null;
switch (shapeType) {
case CIRCLE: return new Circle();
case RECTANGLE: return new Rectangle();
case SQUARE: return new Square();
case TRIANGLE: return new Triangle();
default: return null;
}
}

@Override
public Color getColor(ColorType colorType) {
return null;
}
}

public enum FactoryType {
/**
* 图形工厂
*/
SHAPE,

/**
* 颜色工厂
*/
COLOR
}

public class Run {
public static void main(String[] args) {
//获取图形工厂
AbstractFactory shapeFactory = ProducerFactory.getFactory(FactoryType.SHAPE);
ShapeType[] shapeTypes = ShapeType.values();
for (ShapeType shapeType: shapeTypes) {
Shape shape = shapeFactory.getShape(shapeType);
shape.draw();
}

//获取颜色工厂
AbstractFactory colorFactory = ProducerFactory.getFactory(FactoryType.COLOR);
ColorType[] colorTypes = ColorType.values();
for (ColorType colorType: colorTypes) {
Color color = colorFactory.getColor(colorType);
color.fill();
}

Color color = shapeFactory.getColor(ColorType.RED);
System.out.println(color);
}
}

方法工厂模式

方法工厂模式(Method Factory Pattern),适用于同一属性产品,不同的生产工厂。

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
120
121
122
123
124
125
public abstract class Car {
public String name;

public abstract String getCarName();
}

public class BJ30 extends Car {
public String name = "BJ30";

@Override
public String getCarName() {
return name;
}
}

public class BJ40 extends Car {
public String name = "BJ40";

@Override
public String getCarName() {
return name;
}
}

public class BJ80 extends Car {
private String name = "BJ80";

@Override
public String getCarName() {
return name;
}
}

public class BM5X extends Car {
public String name = "宝马5X";

@Override
public String getCarName() {
return name;
}
}

public class BM7X extends Car {
public String name = "宝马7X";

@Override
public String getCarName() {
return name;
}
}

public class BM9X extends Car {
public String name = "宝马9X";

@Override
public String getCarName() {
return name;
}
}

public enum CarType {
BM5X, BM7X, BM9X, BJ30, BJ40, BJ80
}

public abstract class CarFactory {
public abstract Car createCar(CarType carType);

public static CarFactory getBMFactory() {
return new BMFactory();
}

public static CarFactory getBJFactory() {
return new BJFactory();
}
}

public class BJFactory extends CarFactory {
@Override
public Car createCar(CarType carType) {
if (carType == null)
return null;
switch (carType) {
case BJ30: return new BJ30();
case BJ40: return new BJ40();
case BJ80: return new BJ80();
default: return null;
}
}
}

public class BMFactory extends CarFactory {
@Override
public Car createCar(CarType carType) {
if (carType == null)
return null;
switch (carType) {
case BM5X: return new BM5X();
case BM7X: return new BM7X();
case BM9X: return new BM9X();
default: return null;
}
}
}

public class Run {
public static void main(String[] args) {
CarType[] values = CarType.values();

CarFactory bmFactory = CarFactory.getBMFactory();
for (CarType value : values) {
Car car = bmFactory.createCar(value);
if (car != null) {
System.out.println(car.getCarName());
}
}

CarFactory bjFactory = CarFactory.getBJFactory();
for (CarType value : values) {
Car car = bjFactory.createCar(value);
if (car != null) {
System.out.println(car.getCarName());
}
}
}
}

建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

建造者模式有很多变种,但是万变不离其宗。

结构

  • 产品
  • 建造者抽象类
  • 建造者实现类
  • 指挥者/调用者(自由组合)

例一

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* 产品:课程
*/
public class Course {
private String name;//课程名称

private String ppt;//课程PPT

private String video;//课程视频

private String note;//课程笔记

private String homework;//课后作业

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPpt() {
return ppt;
}

public void setPpt(String ppt) {
this.ppt = ppt;
}

public String getVideo() {
return video;
}

public void setVideo(String video) {
this.video = video;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

public String getHomework() {
return homework;
}

public void setHomework(String homework) {
this.homework = homework;
}

@Override
public String toString() {
return "Course{" +
"name='" + name + '\'' +
", ppt='" + ppt + '\'' +
", video='" + video + '\'' +
", note='" + note + '\'' +
", homework='" + homework + '\'' +
'}';
}
}

/**
* 建造者抽象类
*/
public interface Builder {
Course build();
}

/**
* 建造者实现类
*/
public class CourseBuilder implements Builder {

private Course course = new Course();

public CourseBuilder setName(String name) {
course.setName(name);
return this;
}

public CourseBuilder setPpt(String ppt) {
course.setPpt(ppt);
return this;
}

public CourseBuilder setVideo(String video) {
course.setVideo(video);
return this;
}

public CourseBuilder setNote(String note) {
course.setNote(note);
return this;
}

public CourseBuilder setHomework(String homework) {
course.setHomework(homework);
return this;
}

@Override
public Course build() {
return course;
}
}

/**
* 调用者
*/
public class Run {
public static void main(String[] args) {
CourseBuilder builder = new CourseBuilder();
builder.setName("Sketch-新建画布");
builder.setPpt("Sketch-PPT");
builder.setVideo("Sketch-Video");
builder.setNote("Sketch-快捷键:A");
builder.setHomework("课后新建几张Mac不同尺寸的画布");
System.out.println(builder.build());

CourseBuilder builderSj = new CourseBuilder()
.setName("设计模式")
.setPpt("设计模式PPT")
.setVideo("设计模式视频")
.setNote("设计模式笔记")
.setHomework("设计模式课后作业");
System.out.println(builderSj.build());
}
}

例二

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
* 产品
*/
public class Computer {
private String name;//电脑名称

private String mainBoard;//主板

private String computerChip;//芯片

private String graphicsCard;//显卡

private String memoryModule;//内存

private String displayScreen;//显示屏

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getMainBoard() {
return mainBoard;
}

public void setMainBoard(String mainBoard) {
this.mainBoard = mainBoard;
}

public String getComputerChip() {
return computerChip;
}

public void setComputerChip(String computerChip) {
this.computerChip = computerChip;
}

public String getGraphicsCard() {
return graphicsCard;
}

public void setGraphicsCard(String graphicsCard) {
this.graphicsCard = graphicsCard;
}

public String getMemoryModule() {
return memoryModule;
}

public void setMemoryModule(String memoryModule) {
this.memoryModule = memoryModule;
}

public String getDisplayScreen() {
return displayScreen;
}

public void setDisplayScreen(String displayScreen) {
this.displayScreen = displayScreen;
}

@Override
public String toString() {
return "Computer{" +
"name='" + name + '\'' +
", mainBoard='" + mainBoard + '\'' +
", computerChip='" + computerChip + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
", memoryModule='" + memoryModule + '\'' +
", displayScreen='" + displayScreen + '\'' +
'}';
}
}

/**
* 建造者抽象类
*/
public abstract class Builder {
protected Computer computer = new Computer();

public abstract Builder setName(String name);
public abstract Builder setMainBoard(String mainBoard);
public abstract Builder setComputerChip(String computerChip);
public abstract Builder setGraphicsCard(String graphicsCard);
public abstract Builder setMemoryModule(String memoryModule);
public abstract Builder setDisplayScreen(String displayScreen);

public Computer build() {
return computer;
};
}

public class HpBuilder extends Builder {
@Override
public Builder setName(String name) {
computer.setName(name);
return this;
}

@Override
public Builder setMainBoard(String mainBoard) {
System.out.println("去惠普代工厂拿:" + mainBoard);
computer.setMainBoard(mainBoard);
return this;
}

@Override
public Builder setComputerChip(String computerChip) {
System.out.println("去惠普代工厂拿:" + computerChip);
computer.setComputerChip(computerChip);
return this;
}

@Override
public Builder setGraphicsCard(String graphicsCard) {
System.out.println("去惠普代工厂拿:" + graphicsCard);
computer.setGraphicsCard(graphicsCard);
return this;
}

@Override
public Builder setMemoryModule(String memoryModule) {
System.out.println("去惠普代工厂拿:" + memoryModule);
computer.setMemoryModule(memoryModule);
return this;
}

@Override
public Builder setDisplayScreen(String displayScreen) {
System.out.println("去惠普代工厂拿:" + displayScreen);
computer.setDisplayScreen(displayScreen);
return this;
}
}

public class MacBuilder extends Builder {
@Override
public Builder setName(String name) {
computer.setName(name);
return this;
}

@Override
public Builder setMainBoard(String mainBoard) {
System.out.println("去Mac代工厂拿:" + mainBoard);
computer.setMainBoard(mainBoard);
return this;
}

@Override
public Builder setComputerChip(String computerChip) {
System.out.println("去Mac代工厂拿:" + computerChip);
computer.setComputerChip(computerChip);
return this;
}

@Override
public Builder setGraphicsCard(String graphicsCard) {
System.out.println("去Mac代工厂拿:" + graphicsCard);
computer.setGraphicsCard(graphicsCard);
return this;
}

@Override
public Builder setMemoryModule(String memoryModule) {
System.out.println("去Mac代工厂拿:" + memoryModule);
computer.setMemoryModule(memoryModule);
return this;
}

@Override
public Builder setDisplayScreen(String displayScreen) {
System.out.println("去Mac代工厂拿:" + displayScreen);
computer.setDisplayScreen(displayScreen);
return this;
}
}

public class Director {
Builder builder = null;

public Director(Builder builder) {
this.builder = builder;
}

public void setBuilder(Builder builder) {
this.builder = builder;
}

/**
* @param name 电脑名称
* @param mainBoard 电脑主板
* @param computerChip 电脑芯片
* @param graphicsCard 电脑显卡
* @param memoryModule 电脑内存
* @param displayScreen 电脑显示屏
* @return Computer
*/
public Computer buyComputer(String name, String mainBoard, String computerChip, String graphicsCard, String memoryModule, String displayScreen) {
builder.setName(name);
builder.setMainBoard(mainBoard);
builder.setComputerChip(computerChip);
builder.setGraphicsCard(graphicsCard);
builder.setMemoryModule(memoryModule);
builder.setDisplayScreen(displayScreen);
return builder.build();
}
}

public class Run {
public static void main(String[] args) {
HpBuilder hpBuilder = new HpBuilder();
Director director = new Director(hpBuilder);
Computer hp = director.buyComputer("暗夜精灵", "惠普主板", "i9", "RTX2060", "16G", "17英寸");
System.out.println(hp.toString());

MacBuilder macBuilder = new MacBuilder();
director.setBuilder(macBuilder);
Computer mac = director.buyComputer("MacBookPro", "Apple主板", "M2", "16核神经网络引擎", "16G", "14 英寸 Liquid 视网膜 XDR 显示屏²");
System.out.println(mac.toString());
}
}

例三

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
public abstract class House {
public String door;//门

public String window;//窗

public String yard;//院子

public String getDoor() {
return door;
}

public void setDoor(String door) {
this.door = door;
}

public String getWindow() {
return window;
}

public void setWindow(String window) {
this.window = window;
}

public String getYard() {
return yard;
}

public void setYard(String yard) {
this.yard = yard;
}

@Override
public String toString() {
return "House{" +
"door='" + door + '\'' +
", window='" + window + '\'' +
", yard='" + yard + '\'' +
'}';
}
}

public class CommonHouse extends House{
public void other() {
System.out.println("其他功能");
}
}

public class VillaHouse extends House {
public void fun() {
System.out.println("别墅特殊功能");
}
}

public abstract class Builder {
public abstract Builder setDoor(String door);
public abstract Builder setWindow(String window);
public abstract Builder setYard(String yard);

public abstract Object build();
}

public class CommonHouseBuilder extends Builder {
private CommonHouse commonHouse;

public CommonHouseBuilder() {
this.commonHouse = new CommonHouse();
}

@Override
public Builder setDoor(String door) {
commonHouse.setDoor(door);
return this;
}

@Override
public Builder setWindow(String window) {
commonHouse.setWindow(window);
return this;
}

@Override
public Builder setYard(String yard) {
commonHouse.setYard(yard);
return this;
}

@Override
public CommonHouse build() {
return commonHouse;
}
}

public class VillaHouseBuilder extends Builder {
private VillaHouse villaHouse;

public VillaHouseBuilder() {
villaHouse = new VillaHouse();
}

@Override
public Builder setDoor(String door) {
villaHouse.setDoor(door);
return this;
}

@Override
public Builder setWindow(String window) {
villaHouse.setWindow(window);
return this;
}

@Override
public Builder setYard(String yard) {
villaHouse.setYard(yard);
return this;
}

@Override
public VillaHouse build() {
return villaHouse;
}
}

public class Director {
private Builder builder;

public Director(Builder builder) {
this.builder = builder;
}

public void buildHouse_2D_4W_1Y() {
builder.setDoor("两个门").setWindow("四个窗").setYard("一个院子");
}

public void buildHouse_4D_8W_2Y() {
builder.setDoor("四个门").setWindow("八个窗").setYard("两个院子");
}
}

public class Run {
public static void main(String[] args) {
CommonHouseBuilder commonHouseBuilder = new CommonHouseBuilder();
Director director = new Director(commonHouseBuilder);
director.buildHouse_2D_4W_1Y();
CommonHouse commonHouse = commonHouseBuilder.build();
System.out.println(commonHouse.toString());
commonHouse.other();

VillaHouseBuilder villaHouseBuilder = new VillaHouseBuilder();
Director director1 = new Director(villaHouseBuilder);
director1.buildHouse_4D_8W_2Y();
VillaHouse villaHouse = villaHouseBuilder.build();
System.out.println(villaHouse.toString());
villaHouse.fun();
}
}

结构型模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

类适配器模式

  • 适配器类继承被适配者类
  • 适配器类转化被适配者类中的方法
  • 使用者类调用适配器类中的方法获取想要的值
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
public class Voltage220V {
public int output220V() {
System.out.println("输出220V电压");
return 220;
}
}

public interface Voltage5V {
public int output5v();
}

public class VoltageAdapter extends Voltage220V implements Voltage5V {
@Override
public int output5v() {
int srcV = output220V();
int dstV = srcV / 44;
System.out.println("转化为5V的电压");
return dstV;
}
}

public class mobilePhone {
public void charging(Voltage5V voltage5V) {
if (voltage5V.output5v() == 5){
System.out.println("手机开始充电...");
}
}
}

public class Run {
public static void main(String[] args) {
mobilePhone mobilePhone = new mobilePhone();
mobilePhone.charging(new VoltageAdapter());
}
}

对象适配器模式

  • 适配器类聚合被适配者类
  • 适配器类转化被适配者类中的方法
  • 使用者类获取适配器类的实例时传入被适配器类的实例
  • 使用者类调用适配器类中的方法获取想要的值
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
public class Voltage220V {
public int output220V() {
System.out.println("输出220V电压");
return 220;
}
}

public interface Voltage5V {
public int output5v();
}

public class VoltageAdapter implements Voltage5V {
private Voltage220V voltage220V;

public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}

@Override
public int output5v() {
if (voltage220V == null) return 0;
int srcV = voltage220V.output220V();
int dstV = srcV / 44;
System.out.println("转化为5V的电压");
return dstV;
}
}

public class mobilePhone {
public void charging(Voltage5V voltage5V) {
if (voltage5V.output5v() == 5){
System.out.println("手机开始充电...");
}
}
}

public class Run {
public static void main(String[] args) {
mobilePhone mobilePhone = new mobilePhone();
mobilePhone.charging(new VoltageAdapter(new Voltage220V()));
}
}

接口适配器模式

  • 某一个接口中有很多方法,但是只想用其中一个或几个
  • 创建一个抽象类实现接口的全部方法,空方法即可
  • 实例化抽象类,重写想要使用的方法即可
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
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}

public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
//什么也不做
}

@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}

public class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}

@Override
public void playMp4(String fileName) {
//什么也不做
}
}

public interface MediaPlayer {
public void play(String audioType, String fileName);
}

public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;

public MediaAdapter(String audioType){
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}

@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;

@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: "+ fileName);
}
//mediaAdapter 提供了播放其他文件格式的支持
else if(audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. "+ audioType + " format not supported");
}
}
}

public class Run {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();

audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

桥接模式

桥接模式(Bridge Pattern)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

适用于双重维度的情况,就是多对多的概念,桥接类似于关联关系表的概念。

  • 多种操作系统需要播放多种视频格式的文件
  • 多种图形需要填充多种颜色

结构

  • 实现化角色(接口/抽象类)
  • 具体的实现化角色(实现类)实现实现化角色中的方法
  • 抽象化角色(抽象类)聚合实现化角色
  • 扩展抽象化角色,实现抽象化角色中的方法
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
public interface VideoFile {
public void decode(String fileName);
}

public class AviVideoFile implements VideoFile {
@Override
public void decode(String fileName) {
System.out.println("播放avi格式:" + fileName);
}
}

public class Mp4VideoFile implements VideoFile {
@Override
public void decode(String fileName) {
System.out.println("播放mp4格式:" + fileName);
}
}

public class WmVideoFile implements VideoFile {
@Override
public void decode(String fileName) {
System.out.println("播放wmv格式:" + fileName);
}
}

public abstract class OperationSystem {
protected VideoFile videoFile;

public OperationSystem(VideoFile videoFile) {
this.videoFile = videoFile;
}

public abstract void play(String fileName);
}

public class Mac extends OperationSystem {
public Mac(VideoFile videoFile) {
super(videoFile);
}

@Override
public void play(String fileName) {
videoFile.decode(fileName);
}
}

public class Window extends OperationSystem {
public Window(VideoFile videoFile) {
super(videoFile);
}

@Override
public void play(String fileName) {
videoFile.decode(fileName);
}
}

public class Client {
public static void main(String[] args) {
Window window = new Window(new Mp4VideoFile());
window.play("岁月神偷");

Window window1 = new Window(new WmVideoFile());
window1.play("神话");

Mac mac = new Mac(new AviVideoFile());
mac.play("惜往事");
}
}

装饰者模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

结构

  • 抽象构件角色:定义一个抽象接口用以规范->准备接收附加责任的对象
  • 具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责
  • 抽象装饰角色:继承或实现抽象构件,并包含具体构件角色的实例,可以通过其子类扩展具体构建角色的功能
  • 具体装饰角色:实现抽象装饰的相关放啊,并给具体构件对象添加附加的责任
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* 抽象构件角色
*/
public abstract class FastFood {
private String name;//面条名称

private float price;//价格

//获取价格
public abstract float cost();

public FastFood(String name, float price) {
this.name = name;
this.price = price;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public float getPrice() {
return price;
}

public void setPrice(float price) {
this.price = price;
}
}

/**
* 具体构件角色
*/
public class BanMian extends FastFood {
public BanMian() {
super("板面", 15f);
}

@Override
public float cost() {
return getPrice();
}
}

/**
* 具体构件角色
*/
public class MiXian extends FastFood {
public MiXian() {
super("米线", 16f);
}

@Override
public float cost() {
return getPrice();
}
}

/**
* 抽象装饰角色
*/
public abstract class Garnish extends FastFood {
private FastFood fastFood;

public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}

public FastFood getFastFood() {
return fastFood;
}

public Garnish(FastFood fastFood, String name, float price) {
super(name, price);
this.fastFood = fastFood;
}
}

/**
* 具体装饰角色
*/
public class Egg extends Garnish {
public Egg(FastFood fastFood) {
super(fastFood, "鸡蛋", 2f);
}

@Override
public float cost() {
return getPrice() + getFastFood().cost();
}

@Override
public String getName() {
return getFastFood().getName() + super.getName();
}
}

/**
* 具体装饰角色
*/
public class WanZi extends Garnish {
public WanZi(FastFood fastFood) {
super(fastFood, "丸子", 3f);
}

@Override
public float cost() {
return getPrice() + getFastFood().cost();
}

@Override
public String getName() {
return getFastFood().getName() + super.getName();
}
}

public class Client {
public static void main(String[] args) {
//点一份板面
FastFood foot = new BanMian();

//加一个鸡蛋
foot = new Egg(foot);

//加一个丸子
foot = new WanZi(foot);

System.out.println(foot.getName());
System.out.println(foot.cost() + "元");

}
}

代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

代理模式分为:静态代理、动态代理(JDK代理,cglib代理)、防火墙代理、缓存代理、远程代理、同步代理

结构

  • 被代理类的接口类
  • 被代理类
  • 代理类

静态代理

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
/**
* 出售门票:被代理类的接口类
*/
public interface SellTickets {
void sell();
}

/**
* 火车站:被代理类
*/
public class TrainStation implements SellTickets {
@Override
public void sell() {
System.out.println("火车站卖票");
}
}

/**
* 代售点:代理类
*/
public class ProxyPoint implements SellTickets {
private TrainStation trainStation = new TrainStation();

@Override
public void sell() {
System.out.println("代售点收取一些代理费用");
trainStation.sell();
}
}

public class Client {
public static void main(String[] args) {
//创建一个代售点类
ProxyPoint proxyPoint = new ProxyPoint();
//调用代收点卖火车票的方法
proxyPoint.sell();
}
}

JDK代理

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
/**
* 出售门票:被代理类的接口类
*/
public interface SellTickets {
void sell();
}

/**
* 火车站:被代理类
*/
public class TrainStation implements SellTickets {
@Override
public void sell() {
System.out.println("火车站卖票");
}
}

/**
* 获取运行中生成的代理类
*/
public class ProxyFactory {
public Object proxyObj;

public ProxyFactory(Object proxyObj) {
this.proxyObj = proxyObj;
}

public Object getProxyObject() {
return Proxy.newProxyInstance(
proxyObj.getClass().getClassLoader(),
proxyObj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("使用JDK_Proxy动态代理");
return method.invoke(proxyObj, args);
}
});
}
}

public class Client {
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(new TrainStation());
SellTickets proxyObject = (SellTickets) proxyFactory.getProxyObject();
proxyObject.sell();
}
}

cglib代理

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
/**
* 火车站:被代理类
*/
public class TrainStation {
public void sell() {
System.out.println("火车站卖票");
}
}

/**
* 获取运行中生成的代理类
*/
public class ProxyFactory implements MethodInterceptor {
public Object proxyObj;

public ProxyFactory(Object proxyObj) {
this.proxyObj = proxyObj;
}

public Object getProxyObject() {
//创建Enhancer对象,类似于JDK代理中Proxy对象
Enhancer enhancer = new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(proxyObj.getClass());
//设置回调函数
enhancer.setCallback(this);
//创建代理对象
return enhancer.create();
}

@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("使用cglib动态代理");
return method.invoke(proxyObj, objects);
}
}

public class Client {
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory(new TrainStation());
TrainStation proxyObject = (TrainStation) proxyFactory.getProxyObject();
proxyObject.sell();
}
}

外观模式

外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。

这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

结构

  • 功能角色
  • 外观角色
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
/**
* 功能角色:空调
*/
public class AirCondition {
public void on() {
System.out.println("打开空调...");
}

public void off() {
System.out.println("关闭空调...");
}
}

/**
* 功能角色:电灯类
*/
public class Light {
public void on() {
System.out.println("打开电灯...");
}

public void off() {
System.out.println("关闭电灯...");
}
}

/**
* 功能角色:电视
*/
public class TV {
public void on() {
System.out.println("打开电视...");
}

public void off() {
System.out.println("关闭电视...");
}
}

/**
* 外观角色
*/
public class Facade {
private Light light;
private TV tv;
private AirCondition airCondition;

public Facade() {
this.light = new Light();
this.tv = new TV();
this.airCondition = new AirCondition();
}

public void say(String str) {
if (str.contains("打开")) {
on();
} else if (str.contains("关闭")) {
off();
} else {
System.out.println("暂时还没有这个功能...");
}
}

private void on() {
light.on();
tv.on();
airCondition.on();
}

private void off() {
light.off();
tv.off();
airCondition.off();
}
}

public class Client {
public static void main(String[] args) {
Facade facade = new Facade();

facade.say("打开家电");
facade.say("关闭家电");
}
}

享元模式

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

结构

  • 抽象享元角色:通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)
  • 具体享元角色:它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了储存空间,通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。
  • 非享元角色:并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。
  • 享元工厂:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
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
/**
* 抽象享元角色
*/
public abstract class Box {
public abstract String getShape();

public void display(String color) {
System.out.println("方块形状:" + getShape() + ", 颜色:" + color);
}
}

/**
* 具体享元角色
*/
public class IBox extends Box{
@Override
public String getShape() {
return "I";
}
}

/**
* 具体享元角色
*/
public class LBox extends Box{
@Override
public String getShape() {
return "L";
}
}

/**
* 具体享元角色
*/
public class OBox extends Box{
@Override
public String getShape() {
return "O";
}
}

/**
* 享元工厂
*/
public class BoxFactory {
private HashMap<String, Box> map;

private BoxFactory() {
map = new HashMap<>();
map.put("I", new IBox());
map.put("L", new LBox());
map.put("O", new OBox());
}

private static BoxFactory factory = new BoxFactory();
public static BoxFactory getInstance() {
return factory;
}

public Box getShape(String name) {
return map.get(name);
}
}

public class Client {
public static void main(String[] args) {
BoxFactory instance = BoxFactory.getInstance();

Box i = instance.getShape("I");
i.display("灰色");

Box l = instance.getShape("L");
l.display("绿色");

Box o = instance.getShape("O");
o.display("蓝色");

Box o1 = instance.getShape("O");
o1.display("紫色");

System.out.println(o == o1);
}
}

组合模式

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

结构

  • 抽象根节点:定义系统各个层次的共有方法和属性,可以先定义一些默认行为和属性。
  • 树枝节点:定义数值节点的行为,储存子节点,组合树枝节点和叶子节点形成一个树形结构。
  • 叶子节点:叶子节点对象,其 下再无分支,是系统层次遍历的最小单位。
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
/**
* 抽象根节点
*/
public abstract class MenuComponent {
protected String name;//名称

protected int type;//1文件夹,2文件

public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}

public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}

public MenuComponent getChild(int index) {
throw new UnsupportedOperationException();
}

public String getName() {
return name;
}

public abstract void print();
}

/**
* 树枝节点
*/
public class Menu extends MenuComponent {
private List<MenuComponent> menuComponentList = new ArrayList<>();

public Menu(String name, int type) {
this.name = name;
this.type = type;
}

@Override
public void add(MenuComponent menuComponent) {
menuComponentList.add(menuComponent);
}

@Override
public void remove(MenuComponent menuComponent) {
menuComponentList.remove(menuComponent);
}

@Override
public MenuComponent getChild(int index) {
return menuComponentList.get(index);
}

@Override
public void print() {
String s = type == 1 ? ">" : "-";
System.out.println(s + " " + name);
menuComponentList.forEach(MenuComponent::print);
}
}

/**
* 叶子节点
*/
public class MenuItem extends MenuComponent {
public MenuItem(String name, int type) {
this.name = name;
this.type = type;
}

@Override
public void print() {
String s = type == 1 ? ">" : "-";
System.out.println(s + " " + name);
}
}

public class Client {
public static void main(String[] args) {
MenuComponent menu1 = new Menu("菜单管理", 1);
menu1.add(new MenuItem("页面访问", 2));
menu1.add(new MenuItem("展开菜单", 2));
menu1.add(new MenuItem("编辑菜单", 2));
menu1.add(new MenuItem("删除菜单", 2));
menu1.add(new MenuItem("新增菜单", 2));

MenuComponent menu2 = new Menu("权限管理", 1);
menu2.add(new MenuItem("页面访问", 2));
MenuItem menuItem = new MenuItem("提交保存", 2);
menu2.add(menuItem);
menu2.remove(menuItem);

MenuComponent menu3 = new Menu("角色管理", 1);
menu3.add(new MenuItem("页面访问", 2));
menu3.add(new MenuItem("新增角色", 2));
menu3.add(new MenuItem("修改角色", 2));
menu3.add(new MenuItem("删除角色", 2));

MenuComponent menuSys = new Menu("系统管理", 1);
menuSys.add(menu1);
menuSys.add(menu2);
menuSys.add(menu3);

MenuComponent menuEmploy = new Menu("员工管理", 1);

MenuComponent company = new Menu("公司管理平台", 1);
company.add(menuSys);
company.add(menuEmploy);

company.print();

MenuComponent child = company.getChild(0).getChild(1);
child.print();
}
}

行为型模式

这些设计模式特别关注对象之间的通信。

模板模式

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

结构

  • 抽象类:负责给出一个算法的轮廓和骨架,它由一个模板方法和若干个基本方法构成
    • 模板方法:定义了算法的骨架,按某种顺序调用其包含的方法
    • 基本方法:实现算法的各个步骤的方法,是模板方法的组成部分,基本方法可以分为三种
    • 抽象方法:一个抽象方法有抽象类声明、由其具体子类实现
    • 具体方法:一个具体方法由一个抽象类或具体类声明实现,其子类可以进行覆盖也可以直接继承
    • 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种,一般钩子方法是用于判断的逻辑方法,返回值类型为Boolean。
  • 具体子类:实现抽象类中定义所定义的抽象方法和钩子方法,他们是一个顶级逻辑的组成步骤。
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
public abstract class SoyaMilk {
//模板方法,final修饰,不让子类覆盖
public final void make() {
select();
if (isAddCondiments()) {
addCondiments();
}
soak();
beat();
}

//选材料
public void select() {
System.out.println("选材料:选择新鲜的黄豆");
}

//添加不同的配料,由子类去实现
public abstract void addCondiments();

//浸泡
public void soak() {
System.out.println("开始浸泡,需要三个小时");
}

public void beat() {
System.out.println("放入豆浆机开始制作豆浆");
}

//钩子方法//是否需要添加配料
public boolean isAddCondiments() {
return true;
}
}

public class ChunSoyaMilk extends SoyaMilk {
@Override
public void addCondiments() {
//没有这个步骤,可以空实现
}

@Override
public boolean isAddCondiments() {
return false;
}
}

public class HongdouSoyaMilk extends SoyaMilk {
@Override
public void addCondiments() {
System.out.println("添加红豆配料");
}
}

public class HongzaoSoyaMilk extends SoyaMilk {
@Override
public void addCondiments() {
System.out.println("添加红枣配料");
}
}

public class Client {
public static void main(String[] args) {
System.out.println("--- 制作红豆豆浆 ---");
SoyaMilk hongdouSoyaMilk = new HongdouSoyaMilk();
hongdouSoyaMilk.make();

System.out.println("--- 制作红枣豆浆 ---");
SoyaMilk hongzaoSoyaMilk = new HongzaoSoyaMilk();
hongzaoSoyaMilk.make();

System.out.println("--- 制作纯豆浆 ---");
SoyaMilk chunSoyaMilk = new ChunSoyaMilk();
chunSoyaMilk.make();
}
}

命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

结构

  • 抽象命令类角色:定义命令接口,声明执行的方法
  • 具体命令角色:具体的命令,实现命令接口,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
  • 实现者/接收者角色:真正执行命令的对象,任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能
  • 调用者/请求者角色:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象,这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的接口。
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* 抽象命令类角色
*/
public interface Command {
//执行命令
public void execute();

//撤销命令
public void undo();
}

/**
* 具体命令角色
*/
public class DengpaoOffCommand implements Command{
Dengpao dengpao;

public DengpaoOffCommand(Dengpao dengpao) {
this.dengpao = dengpao;
}

@Override
public void execute() {
dengpao.off();
}

@Override
public void undo() {
dengpao.on();
}
}

/**
* 具体命令角色
*/
public class DengpaoOnCommand implements Command{
Dengpao dengpao;

public DengpaoOnCommand(Dengpao dengpao) {
this.dengpao = dengpao;
}

@Override
public void execute() {
dengpao.on();
}

@Override
public void undo() {
dengpao.off();
}
}

/**
* 具体命令角色(空命令),用于初始化命令,当调用空命令时,对象什么都不做。
*/
public class NoCommand implements Command{
@Override
public void execute() {

}

@Override
public void undo() {

}
}

/**
* 灯泡 实现者/接收者角色
*/
public class Dengpao {
public void on() {
System.out.println("灯泡打开了...");
}

public void off() {
System.out.println("灯泡关闭了...");
}
}

public class RemoteController {
//要执行的命令
Map<String, Command> onCommands;
Map<String, Command> offCommands;

//撤销命令
Command undoCommand;

public RemoteController() {
onCommands = new HashMap<>();
offCommands = new HashMap<>();
}

public void setCommand(String commandKey, Command onCommand, Command offCommand) {
onCommands.put(commandKey, onCommand);
offCommands.put(commandKey, offCommand);
}

public void onButtonPushed(String commandKey) {
Command command = onCommands.get(commandKey);
if (command != null) {
//执行命令
command.execute();
//用于撤销命令
undoCommand = command;
}
}

public void offButtonPushed(String commandKey) {
Command command = offCommands.get(commandKey);
if (command != null) {
//执行命令
command.execute();
//用于撤销命令
undoCommand = command;
}
}

public void undoButtonPushed() {
if (undoCommand != null) {
undoCommand.undo();
}
}
}

public class Client {
public static void main(String[] args) {
//灯泡实例(实现者/接收者角色)
Dengpao dengpao = new Dengpao();
//操作灯泡的命令(具体命令角色)
DengpaoOnCommand dengpaoOnCommand = new DengpaoOnCommand(dengpao);
DengpaoOffCommand dengpaoOffCommand = new DengpaoOffCommand(dengpao);

//遥控器(调用者/请求者角色)
RemoteController remoteController = new RemoteController();

//添加命令
String dengpaoCommandKey = "dengpao";
remoteController.setCommand(dengpaoCommandKey, dengpaoOnCommand, dengpaoOffCommand);

//执行命令
remoteController.onButtonPushed(dengpaoCommandKey);
remoteController.offButtonPushed(dengpaoCommandKey);
remoteController.undoButtonPushed();
}
}

策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。

通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

结构

  • 环境角色:持有一个策略类的引用,最终给客户端调用。
  • 抽象策略角色:通常由一个接口或者是抽象类实现,此角色给出所有的具体策略类所需的接口。
  • 具体策略角色:实现了抽象策略定义的接口,提供具体的算法实现或行为。
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
/**
* 抽象策略角色
*/
public interface Strategy {
void show();
}

/**
* 具体策略角色
*/
public class StrategyA implements Strategy {
@Override
public void show() {
System.out.println("买一送一");
}
}

/**
* 具体策略角色
*/
public class StrategyB implements Strategy {
@Override
public void show() {
System.out.println("满二百减五十");
}
}

/**
* 具体策略角色
*/
public class StrategyC implements Strategy {
@Override
public void show() {
System.out.println("满加一千元加一元换购任意二百元以下商品");
}
}

/**
* 环境角色
*/
public class SaleMan {
private Strategy strategy;

public SaleMan(Strategy strategy) {
this.strategy = strategy;
}

public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}

public void show() {
strategy.show();
}
}

public class Client {
public static void main(String[] args) {
SaleMan saleMan = new SaleMan(new StrategyA());
saleMan.show();

saleMan.setStrategy(new StrategyB());
saleMan.show();

saleMan.setStrategy(new StrategyC());
saleMan.show();
}
}

责任链模式

责任链模式(Chain of Responsibility Pattern),又叫职责链模式,该模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链, 当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

结构

  • 抽象处理者角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者角色:实现抽象处理者的处理方法,判断是否可以处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类角色:创建处理链,并将链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* 抽象处理者角色
*/
public abstract class Handler {
//请假天数
protected final static int NUM_ONE = 1;
protected final static int NUM_THREE = 3;
protected final static int NUM_SEVEN = 7;

//请假区间
private int numStart;
private int numEnd;

//下一个处理者
private Handler nextHandler;

public Handler(int numStart) {
this.numStart = numStart;
}

public Handler(int numStart, int numEnd) {
this.numStart = numStart;
this.numEnd = numEnd;
}

public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}

//处理请假请求
protected abstract void handlerLeave(LeaveRequest leave);

//提交请假请求
public final void submit(LeaveRequest leave) {
if (this.numStart <= leave.getNum() && leave.getNum() <= this.numEnd) {
this.handlerLeave(leave);
} else if (this.nextHandler != null) {
this.nextHandler.submit(leave);
} else {
System.out.println("请假天数不符合规定");
}
}
}

/**
* 具体处理者角色:总经理
*/
public class GeneralLeader extends Handler{
public GeneralLeader() {
super(NUM_THREE, NUM_SEVEN);
}

@Override
protected void handlerLeave(LeaveRequest leave) {
System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
System.out.println("总经理审批:同意");
}
}

/**
* 具体处理者角色:部门经理
*/
public class ManagerLeader extends Handler{
public ManagerLeader() {
super(NUM_ONE, NUM_THREE);
}

@Override
protected void handlerLeave(LeaveRequest leave) {
System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
System.out.println("部门经理审批:同意");
}
}

/**
* 具体处理者角色:小组长
*/
public class GroupLeader extends Handler{
public GroupLeader() {
super(0, NUM_ONE);
}

@Override
protected void handlerLeave(LeaveRequest leave) {
System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent());
System.out.println("小组长审批:同意");
}
}

/**
* 请假条实体
*/
public class LeaveRequest {
//姓名
private String name;

//天数
private int num;

//内容
private String content;

public LeaveRequest(String name, int num, String content) {
this.name = name;
this.num = num;
this.content = content;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getNum() {
return num;
}

public void setNum(int num) {
this.num = num;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}

public class Client {
public static void main(String[] args) {
LeaveRequest request = new LeaveRequest("小明", 8, "身体不适!");

GroupLeader groupLeader = new GroupLeader();
ManagerLeader managerLeader = new ManagerLeader();
GeneralLeader generalLeader = new GeneralLeader();

groupLeader.setNextHandler(managerLeader);
managerLeader.setNextHandler(generalLeader);

groupLeader.submit(request);
}
}

状态模式

在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。

对有状态的对象,把复杂的判断逻辑提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

结构

  • 环境角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将于状态相关的操作委托给当前状态对象来处理。
  • 抽象状态角色:定义一个接口,用于封装环境对象中的特定状态所对应的行为。
  • 具体状态角色:实现抽象状态所对应的行为。
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/**
* 环境角色
*/
public class Context {
public final static OpenState OPEN_STATE = new OpenState();

public final static CloseState CLOSE_STATE = new CloseState();

public final static RunState RUN_STATE = new RunState();

public final static StopState STOP_STATE = new StopState();

private LiftState liftState;

public LiftState getLiftState() {
return liftState;
}

public void setLiftState(LiftState liftState) {
this.liftState = liftState;
this.liftState.setContext(this);
}

public void open(){
this.liftState.open();
};
public void close(){
this.liftState.close();
};
public void run(){
this.liftState.run();
};
public void stop(){
this.liftState.stop();
};
}

/**
* 抽象状态角色
*/
public abstract class LiftState {
protected Context context;

public void setContext(Context context) {
this.context = context;
}

public abstract void open();
public abstract void close();
public abstract void run();
public abstract void stop();
}

/**
* 具体状态角色
*/
public class CloseState extends LiftState {
@Override
public void open() {
super.context.setLiftState(Context.OPEN_STATE);
super.context.open();
}

@Override
public void close() {
System.out.println("电梯关闭...");
}

@Override
public void run() {
super.context.setLiftState(Context.RUN_STATE);
super.context.run();
}

@Override
public void stop() {
super.context.setLiftState(Context.STOP_STATE);
super.context.stop();
}
}

/**
* 具体状态角色
*/
public class OpenState extends LiftState {
@Override
public void open() {
System.out.println("电梯开启...");
}

@Override
public void close() {
super.context.setLiftState(Context.CLOSE_STATE);
super.context.close();
}

@Override
public void run() {

}

@Override
public void stop() {

}
}

/**
* 具体状态角色
*/
public class RunState extends LiftState {
@Override
public void open() {

}

@Override
public void close() {

}

@Override
public void run() {
System.out.println("电梯正在运行...");
}

@Override
public void stop() {
super.context.setLiftState(Context.STOP_STATE);
super.context.stop();
}
}

/**
* 具体状态角色
*/
public class StopState extends LiftState {
@Override
public void open() {
super.context.setLiftState(Context.OPEN_STATE);
super.context.open();
}

@Override
public void close() {
super.context.setLiftState(Context.CLOSE_STATE);
super.context.close();
}

@Override
public void run() {
super.context.setLiftState(Context.RUN_STATE);
super.context.run();
}

@Override
public void stop() {
System.out.println("电梯停止了...");
}
}

public class Client {
public static void main(String[] args) {
Context context = new Context();
context.setLiftState(new RunState());

context.open();
context.close();
context.run();
context.stop();

context.open();
}
}

观察者模式

观察者模式(Observer Pattern)又被称之为发布-订阅模式,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

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

JDK源码:java.util.Observable

结构

  • 抽象主题(抽象被观察者):抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  • 具体主题(具体被观察者):该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  • 抽象观察者:是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  • 具体观察者:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自己的状态。
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
/**
* 抽象主题(抽象被观察者)
*/
public interface Subject {
//添加订阅者
public void add(Observer o);

//移除订阅者
public void remove(Observer o);

//发送通知
public void notify(String message);
}

/**
* 具体主题(具体被观察者)
*/
public class SubscriptionSubject implements Subject {
private ArrayList<Observer> observers = new ArrayList<>();

@Override
public void add(Observer o) {
observers.add(o);
}

@Override
public void remove(Observer o) {
observers.remove(o);
}

@Override
public void notify(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}

/**
* 抽象观察者
*/
public interface Observer {
public void update(String message);
}

/**
* 具体观察者
*/
public class WeXinUser implements Observer {
private String name;

public WeXinUser(String name) {
this.name = name;
}

@Override
public void update(String message) {
System.out.println(name+"接到更新通知:"+message);
}
}

public class Client {
public static void main(String[] args) {
SubscriptionSubject subscriptionSubject = new SubscriptionSubject();

subscriptionSubject.add(new WeXinUser("孙悟空"));
subscriptionSubject.add(new WeXinUser("猪悟能"));
subscriptionSubject.add(new WeXinUser("沙悟净"));

subscriptionSubject.notify("师傅被妖怪抓走了。。。");
}
}

中介者模式

中介者模式(Mediator Pattern),又叫调停模式,是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。

定义一个中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

结构

  • 抽象中介者角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  • 具体中介者角色:实现中介者接口,定义一个List来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类角色:定义同事类接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
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
/**
* 抽象中介者角色
*/
public abstract class Mediator {
public abstract void contact(String message, Person person);
}

/**
* 具体中介者角色
*/
public class MediatorStructure extends Mediator {
private HouseOwner houseOwner;

private Tenant tenant;

@Override
public void contact(String message, Person person) {
if (person == houseOwner) {
tenant.getMessage(message);
} else {
houseOwner.getMessage(message);
}
}

public HouseOwner getHouseOwner() {
return houseOwner;
}

public void setHouseOwner(HouseOwner houseOwner) {
this.houseOwner = houseOwner;
}

public Tenant getTenant() {
return tenant;
}

public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
}

/**
* 抽象同事类角色
*/
public abstract class Person {
protected String name;

protected Mediator mediator;

public Person(String name, Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
}

/**
* 具体同事类角色
*/
public class HouseOwner extends Person {
public HouseOwner(String name, Mediator mediator) {
super(name, mediator);
}

public void contact(String message) {
mediator.contact(message, this);
}

public void getMessage(String message) {
System.out.println("房主" + name + "获取到的信息是:" + message);
}
}

/**
* 具体同事类角色
*/
public class Tenant extends Person {
public Tenant(String name, Mediator mediator) {
super(name, mediator);
}

public void contact(String message) {
mediator.contact(message, this);
}

public void getMessage(String message) {
System.out.println("租房者" + name + "获取到的信息是:" + message);
}
}

public class Client {
public static void main(String[] args) {
MediatorStructure mediatorStructure = new MediatorStructure();
Tenant tenant = new Tenant("李四", mediatorStructure);
HouseOwner houseOwner = new HouseOwner("张三", mediatorStructure);

mediatorStructure.setTenant(tenant);
mediatorStructure.setHouseOwner(houseOwner);

tenant.contact("我要租三室的房子!");
houseOwner.contact("我这里有三室的房子你要租吗?");
}
}

迭代器模式

迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

结构

  • 抽象聚合角色:定义储存、添加、删除聚合元素以及创建迭代器对象的接口
  • 具体聚合角色:实现抽象聚合类,返回一个具体迭代器的实例。
  • 抽象迭代器角色:定义访问和遍历聚合元素的接口,通常包含hasNext()、next()等方法。
  • 具体迭代器角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
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
120
121
122
123
124
125
/**
* 实体
*/
public class Student {
private String name;

private String number;

public Student(String name, String number) {
this.name = name;
this.number = number;
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", number='" + number + '\'' +
'}';
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}
}

/**
* 抽象聚合角色
*/
public interface StudentAggregate {
//添加
void addStudent(Student student);

//删除
void removeStudent(Student student);

//获取迭代器
StudentIterator getStudentIterator();
}

/**
* 具体聚合角色
*/
public class StudentAggregateImpl implements StudentAggregate {
private List<Student> list = new ArrayList<>();

@Override
public void addStudent(Student student) {
list.add(student);
}

@Override
public void removeStudent(Student student) {
list.remove(student);
}

@Override
public StudentIterator getStudentIterator() {
return new StudentIteratorImpl(list);
}
}


/**
* 抽象迭代器角色
*/
public interface StudentIterator {
//判断是否还有元素
boolean hasNext();

//获取下一个元素
Student next();
}

/**
* 具体迭代器角色
*/
public class StudentIteratorImpl implements StudentIterator {
private List<Student> list;
private int position = 0;

public StudentIteratorImpl(List<Student> list) {
this.list = list;
}

@Override
public boolean hasNext() {
return position < list.size();
}

@Override
public Student next() {
Student student = list.get(position);
position++;
return student;
}
}

public class Client {
public static void main(String[] args) {
StudentAggregateImpl aggregate = new StudentAggregateImpl();
aggregate.addStudent(new Student("张三", "001"));
aggregate.addStudent(new Student("李四", "002"));
aggregate.addStudent(new Student("王五", "003"));
aggregate.addStudent(new Student("赵六", "004"));

StudentIterator iterator = aggregate.getStudentIterator();
while (iterator.hasNext()){
Student next = iterator.next();
System.out.println(next.toString());
}
}
}

访问者模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。

结构

  • 抽象访问者角色:定义了对每一个元素访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数是一样的,访问者模式要求元素类的个数不能改变。
  • 具体访问者角色:给出对每一个元素类访问时所产生的具体行为。
  • 抽象元素角色:定义了一个接受访问者的方法,其意义是指,每一个元素都要可以被访问者访问。
  • 具体元素角色:提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
  • 对象结构角色:定义当中所提到的对象结构,对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它会含有一组元素,并且可以迭代这些元素,供访问者访问。
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
/**
* 抽象访问者角色
*/
public interface Person {
//给宠物猫喂食
void feed(Cat cat);

//给宠物狗喂食
void feed(Dog cat);
}

/**
* 具体访问者角色
*/
public class Owner implements Person {
@Override
public void feed(Cat cat) {
System.out.println("主人给猫咪喂食...");
}

@Override
public void feed(Dog cat) {
System.out.println("主人给狗狗喂食...");
}
}

/**
* 具体访问者角色
*/
public class Someone implements Person {
@Override
public void feed(Cat cat) {
System.out.println("其他人给猫咪喂食...");
}

@Override
public void feed(Dog cat) {
System.out.println("其他人给狗狗喂食...");
}
}

/**
* 抽象元素角色
*/
public interface Animal {
//接受访问者访问的功能
void accept(Person person);
}

/**
* 具体元素角色
*/
public class Cat implements Animal {
@Override
public void accept(Person person) {
person.feed(this);
System.out.println("喵喵喵...");
}
}

/**
* 具体元素角色
*/
public class Dog implements Animal {
@Override
public void accept(Person person) {
person.feed(this);
System.out.println("汪汪汪...");
}
}

/**
* 对象结构角色
*/
public class Home {
//声明一个集合对象,用来储存元素对象
private List<Animal> animals = new ArrayList<>();

//添加元素对象
public void add(Animal animal) {
animals.add(animal);
}

//访问每个元素
public void action(Person person) {
for (Animal animal:animals) {
animal.accept(person);
}
}
}

public class Client {
public static void main(String[] args) {
Home home = new Home();
home.add(new Cat());
home.add(new Dog());

Owner owner = new Owner();
home.action(owner);
}
}

备忘录模式

备忘录模式(Memento Pattern),又叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。备忘录模式属于行为型模式。

结构

  • 发起人角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  • 备忘录角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  • 管理者角色:对备忘录进行管理,提供保存与获取备忘录功能,但其不能对备忘录的内容进行访问与修改。
  • 备忘录有两个等效的接口
    • 窄接口:管理者对象(和其他发起人对象之外的任何对象)看到的都是备忘录的窄接口,这个窄接口只允许它把备忘录对象传给其他对象。
    • 宽接口:与管理者看到的窄接口相反,发起人对象可以看到一个宽接口,这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。

例一

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
/**
* 备忘录角色:对外提供的窄接口
*/
public interface Memento {
}

/**
* 发起人角色
*/
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力

private class RoleStateMemento implements Memento {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力

public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}

public int getVit() {
return vit;
}

public int getAtk() {
return atk;
}

public int getDef() {
return def;
}
}

//初始化对象
public void initState() {
this.vit = 100;
this.atk = 100;
this.def = 100;
}

//死亡
public void fight() {
this.vit = 0;
this.atk = 0;
this.def = 0;
}

//保存
public Memento savaState() {
return new RoleStateMemento(this.vit, this.atk, this.def);
}

//恢复
public void recoverState(Memento memento) {
RoleStateMemento roleStateMemento = (RoleStateMemento) memento;
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}

//展示
public void stateDisplay() {
System.out.println("======角色面板======");
System.out.println("角色生命力:"+this.vit);
System.out.println("角色攻击力:"+this.atk);
System.out.println("角色防御力:"+this.def);
System.out.println("===================");
}
}

/**
* 管理者角色
*/
public class RoleStateCaretaker {
private Memento memento;

public Memento getMemento() {
return memento;
}

public void setMemento(Memento memento) {
this.memento = memento;
}
}

public class Client {
public static void main(String[] args) {
System.out.println("初始化角色");
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();

//存档
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
Memento roleStateMemento = gameRole.savaState();
roleStateCaretaker.setMemento(roleStateMemento);

System.out.println("角色死亡");
gameRole.fight();
gameRole.stateDisplay();

System.out.println("回档");
gameRole.recoverState(roleStateCaretaker.getMemento());
gameRole.stateDisplay();
}
}

例二

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
/**
* 发起人角色
*/
public class GameRole {
private int vit;//生命力
private int atk;//攻击力
private int def;//防御力

//初始化对象
public void initState() {
this.vit = 100;
this.atk = 100;
this.def = 100;
}

//死亡
public void fight() {
this.vit = 0;
this.atk = 0;
this.def = 0;
}

//保存
public RoleStateMemento savaState() {
return new RoleStateMemento(this.vit, this.atk, this.def);
}

//恢复
public void recoverState(RoleStateMemento roleStateMemento) {
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}

//展示
public void stateDisplay() {
System.out.println("======角色面板======");
System.out.println("角色生命力:"+this.vit);
System.out.println("角色攻击力:"+this.atk);
System.out.println("角色防御力:"+this.def);
System.out.println("===================");
}
}

/**
* 备忘录角色
*/
public class RoleStateMemento {
private int vit;
private int atk;
private int def;

public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}

public int getVit() {
return vit;
}

public void setVit(int vit) {
this.vit = vit;
}

public int getAtk() {
return atk;
}

public void setAtk(int atk) {
this.atk = atk;
}

public int getDef() {
return def;
}

public void setDef(int def) {
this.def = def;
}
}

/**
* 管理者角色
*/
public class RoleStateCaretaker {
private RoleStateMemento roleStateMemento;

public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}

public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}

public class Client {
public static void main(String[] args) {
System.out.println("初始化角色");
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.stateDisplay();

//存档
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
RoleStateMemento roleStateMemento = gameRole.savaState();
roleStateCaretaker.setRoleStateMemento(roleStateMemento);

System.out.println("角色死亡");
gameRole.fight();
gameRole.stateDisplay();

System.out.println("回档");
gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
gameRole.stateDisplay();
}
}

解释器模式

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

结构

  • 抽象表达式角色:定义解释器接口,约定解释器的解释操作。
  • 终结符表达式角色:抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式角色:抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应一个非终结符表达式。
  • 环境角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
  • 客户端:主要任务是将需要分析的句子或者表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,也可以通过环境角色间接访问解释器的解释方法。
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
120
121
122
123
124
125
126
127
128
129
/**
* 抽象表达式角色
*/
public abstract class AbstractExpression {
//解释器的解释方法
public abstract int interpret(Context context);
}

/**
* 封装变量类:终结符表达式角色
*/
public class Variable extends AbstractExpression {
//声明储存变量名的成员变量
private String name;

public Variable(String name) {
this.name = name;
}

@Override
public int interpret(Context context) {
//返回变量的值
return context.getValue(this);
}

@Override
public String toString() {
return name;
}
}

/**
* 减法表达式类:非终结符表达式角色
*/
public class Minus extends AbstractExpression{
//-号左边的表达式
private AbstractExpression left;

//-号右边的表达式
private AbstractExpression right;

public Minus(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}

@Override
public int interpret(Context context) {
return this.left.interpret(context) - this.right.interpret(context);
}

@Override
public String toString() {
return "(" + this.left.toString() + " - " + this.right.toString() + ")";
}
}

/**
* 加法表达式类:非终结符表达式角色
*/
public class Plus extends AbstractExpression{
//+号左边的表达式
private AbstractExpression left;

//+号右边的表达式
private AbstractExpression right;

public Plus(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}

@Override
public int interpret(Context context) {
return this.left.interpret(context) + this.right.interpret(context);
}

@Override
public String toString() {
return "(" + this.left.toString() + " + " + this.right.toString() + ")";
}
}

/**
* 环境角色
*/
public class Context {
//定义一个map集合,用来储存变量及对应的值
private Map<Variable, Integer> map;

public Context() {
map = new HashMap<>();
}

//添加变量的功能
public void assign(Variable variable, Integer value) {
map.put(variable, value);
}

//根据变量获取对应的值
public Integer getValue(Variable variable) {
return map.get(variable);
}
}

public class Client {
public static void main(String[] args) {
//创建环境对象
Context context = new Context();

//创建变量对象
Variable a = new Variable("a");
Variable b = new Variable("b");
Variable c = new Variable("c");
Variable d = new Variable("d");

//将变量存储到环境对象中
context.assign(a, 1);
context.assign(b, 2);
context.assign(c, 3);
context.assign(d, 4);

//获取抽象语法树 a + b - c + d
AbstractExpression abstractExpression = new Plus(a, new Plus(new Minus(b, c), d));
//解释执行
int result = abstractExpression.interpret(context);
System.out.println(abstractExpression + " = " + result);
}
}

学习资源

  • 视频
    • 黑马程序员 Java 设计模式:https://www.bilibili.com/video/BV1Np4y1z7BU
    • 尚硅谷图解 Java 设计模式:https://www.bilibili.com/video/BV1G4411c7N4
  • 书籍
    • 《图解设计模式》
    • 《Head First 设计模式》
    • 《大话设计模式》
    • 《设计模式:可复用面向对象软件的基础》
  • 文档
    • 菜鸟教程:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
    • 图说设计模式:https://design-patterns.readthedocs.io/zh_CN/latest/