设计模式

本文最后更新于:1 年前

Reference


设计模式串联


创建型

单例模式(Singleton)

保证一个类仅有一个实例,并提供一个访问它的全局访问点。
有个人自己开了一家餐厅,这家餐厅只有一个老板。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// InputMethodManager 用于控制显示或隐藏输入法面板
public final class InputMethodManager {
static InputMethodManager sInstance;

InputMethodManager(IInputMethodManager service, Looper looper) {
mService = service;
mMainLooper = looper;
mH = new H(looper);
mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
}

public static InputMethodManager getInstance() {
synchronized (InputMethodManager.class) {
if (sInstance == null) {
try {
sInstance = new InputMethodManager(Looper.getMainLooper());
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
}
return sInstance;
}
}
}

饿汉式

1
2
3
4
5
6
7
8
9
public class SingleTon{
private static SingleTon mSingleTon = new SingleTon();

private SingleTon() {}

public static SingleTon getInstance() {
return mSingleTon;
}
}

懒汉式(线程不安全)

1
2
3
4
5
6
7
8
9
10
11
12
public class SingleTon{
private static SingleTon mSingleTon = null;

private SingleTon() {}

public static SingleTon getInstance() {
if(mSingleTon == null) {
mSingleTon = new SingleTon();
}
return mSingleTon;
}
}

懒汉式(线程安全)

1
2
3
4
5
6
7
8
9
10
11
12
public class SingleTon{
private static SingleTon mSingleTon = null;

private SingleTon() {}

public static synchronized SingleTon getInstance() {
if(mSingleTon == null) {
mSingleTon = new SingleTon();
}
return mSingleTon;
}
}

懒汉式(双重校验锁,线程不一定安全)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingleTon{
private static SingleTon mSingleTon = null;

private SingleTon() {}

public static SingleTon getInstance() {
if(mSingleTon == null){
synchronized(SingleTon.class) {
if(mSingleTon == null) {
mSingleTon = new SingleTon();
}
}
}
return mSingleTon;
}
}

懒汉式(双重校验锁,线程安全)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingleTon{
private static volatile SingleTon mSingleTon = null;

private SingleTon() {}

public static SingleTon getInstance() {
if(mSingleTon == null){
synchronized(SingleTon.class) {
if(mSingleTon == null) {
mSingleTon = new SingleTon();
}
}
}
return mSingleTon;
}
}

枚举

1
2
3
4
5
enum SingleTon {
SINGLE
}

SingleTon.SINGLE

静态内部类

1
2
3
4
5
6
7
8
9
10
11
public class SingleTon {
private static class InnerClass {
static SingleTon mSingleTon = new SingleTon();
}

private SingleTon() {}

public static SingleTon getInstance() {
return InnerClass.mSingleTon;
}
}

建造者模式(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
public class 招人 {
private final int 年龄;
private final int 性别;
private final int 技能;

private 招人(招人要求 要求) {
this.年龄 = 要求.年龄;
this.性别 = 要求.性别;
this.技能 = 要求.技能;
}

public int get年龄() {
return 年龄;
}

public int get性别() {
return 性别;
}

public int get技能() {
return 技能;
}

public static final class 招人要求 {
private int 年龄;
private int 性别;
private final int 技能;

public 招人要求(int 技能) {
this.技能 = 技能;
}

public 招人要求 set年龄(int 年龄) {
this.年龄 = 年龄;
return this;
}

public 招人要求 set性别(int 性别) {
this.性别 = 性别;
return this;
}

public 招人 开始查找() {
return new 招人(this);
}
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
招人 服务员 = new 招人.招人要求(辅助点餐)
.set年龄(60以下)
.set性别(男女均可)
.开始查找();
招人 厨师 = new 招人.招人要求(做菜)
.set年龄(60以下)
.set性别(男女均可)
.开始查找();
}
}

工厂方法模式(FactoryMethod)

定义一个用于创建对象的接口,让子类决定实例化哪一个类。
老板可能从某联上招人,也可能从某勾上招人,某联使用的就是某联的数据库,某勾使用的是某勾的数据库。

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
public interface 服务员 {
void 辅助点餐();
}

public class 某联人才库中的服务员 implements 服务员 {
@Override
public void 辅助点餐() {
System.out.println("某联人才库中的服务员辅助点餐!");
}
}

public class 某勾人才库中的服务员 implements 服务员 {
@Override
public void 辅助点餐() {
System.out.println("某勾人才库中的服务员辅助点餐!");
}
}

public interface 厨师 {
void 做菜();
}

public class 某联人才库中的厨师 implements 厨师 {
@Override
public void 做菜() {
System.out.println("某联人才库中的厨师做菜!");
}
}

public class 某勾人才库中的厨师 implements 厨师 {
@Override
public void 做菜() {
System.out.println("某勾人才库中的厨师做菜!");
}
}

public interface 招聘网站 {
List<员工> 招聘();
}

public class 某联招聘网站 implements 招聘网站 {
@Override
public List<员工> 招聘() {
List<员工> 员工们 = new ArrayList<>(2);
员工们.add(new 某联人才库中的服务员());
员工们.add(new 某联人才库中的厨师());
return 员工们;
}
}

public class 某勾招聘网站 implements 招聘网站 {
@Override
public List<员工> 招聘() {
List<员工> 员工们 = new ArrayList<>(2);
员工们.add(new 某勾人才库中的服务员());
员工们.add(new 某勾人才库中的厨师());
return 员工们;
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
new 某勾招聘网站().招聘();
}
}

抽象工厂模式(AbstractFactory)

为创建一组相关或者是相互依赖的对象提供一个接口,而不需要指定他们的具体实现类。
招聘网站千千万找不过来,老板决定让猎头找。

1
2
3
4
5
6
7
8
9
10
public class 猎头招聘网站 implements 招聘网站 {
@Override
public List<员工> 招聘() {
List<员工> 员工们 = new ArrayList<>(2);
员工们.add(new 某联人才库中的服务员());
员工们.add(new 某勾人才库中的厨师());
return 员工们;
}
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
new 猎头招聘网站().招聘();
}
}

原型模式(Prototype)

创建对象的种类,并通过拷贝这些原型创建新的对象。
餐厅经营得不错,一段时间后,老板开了一家分店,又招了一批服务员和厨师,但是老板还是一个。

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 餐厅 implements Cloneable {
private 老板 唯一的老板;
private List<服务员> 服务员们;
private List<厨师> 厨师们;

public void set老板(老板 唯一的老板) {
this.唯一的老板 = 唯一的老板;
}

public 老板 get老板() {
return this.唯一的老板;
}

public 餐厅 clone() throws CloneNotSupportedException {
餐厅 分店 = (餐厅)super.clone();
分店.set老板(唯一的老板);
return 分店;
}

public String 花名册() {
StringBuilder builder = new StringBuilder();
builder.append("老板:" + 唯一的老板)
.append("服务员们:" + 服务员们)
.append("厨师们:" + 厨师们);
return builder.toString();
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
总店.clone().员工花名册();
}
}

结构型

适配器模式(Adapter)

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。
老板在某聘上招人,因为某聘和某联合作,所以某聘直接使用某联的人才库。

1
2
3
4
5
6
public class 某聘招聘网站 implements 招聘网站 {
@Override
public List<员工> 招聘() {
return new 某联招聘网站().招聘();
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String args[]) {
new 某聘招聘网站().招聘();
}
}

装饰模式(Decorator)

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
当服务员请假时,厨师可以兼任服务员的工作。

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 interface 厨师 {
void 做菜();
}

public abstract class 可以兼任工作的厨师 implements 厨师 {
private 厨师 某个厨师;

public 可以兼任工作的厨师(厨师 某个厨师) {
this.某个厨师 = 某个厨师;
}

@Override
public void 做菜() {
某个厨师.做菜();
}

public abstract void 额外工作();
}

public class 可以兼任服务员的厨师 extends 可以兼任工作的厨师 {
public 可以兼任服务员的厨师(厨师 某个厨师) {
super(某个厨师);
}

@Override
public void 额外工作() {
System.out.println("兼任服务员辅助点餐!");
}
}
  • 测试
1
2
3
4
5
6
7
public class Test {
public static void main(String args[]) {
可以兼任工作的厨师 厨师 = new 可以兼任服务员的厨师(new 某联人才库中的厨师());
厨师.做菜();
厨师.额外工作();
}
}

代理模式(Proxy)

调用原有的方法,且对产生的结果进行控制。
由于洗菜工还未入职,所以厨师做菜前,需要先洗菜。

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 interface 厨师 {
void 做菜();
}

public abstract class 需要承担额外工作的厨师 implements 厨师 {
private 厨师 某个厨师;

public 需要承担额外工作的厨师(厨师 某个厨师) {
this.某个厨师 = 某个厨师;
}

@Override
public void 做菜() {
额外工作();
某个厨师.做菜();
}

public abstract void 额外工作();
}

public class 需要洗菜的厨师 extends 需要承担额外工作的厨师 {
public 需要洗菜的厨师(厨师 某个厨师) {
super(某个厨师);
}

@Override
public void 额外工作() {
System.out.println("厨师洗菜!");
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String args[]) {
new 需要洗菜的厨师(new 某联人才库中的厨师()).做菜();
}
}

组合模式(Composite)

将对象组合成树形结构以表示“部分-整体”的层次结构。
建立管理层,且新店开业后归总店管理。

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 interface Component {
void add(Component component);

void remove(Component component);
}

public class 客服部 implements Component {
private List<Component> list = new ArrayList<>();

@Override
public void add(Component component) {
list.add(component);
}

@Override
public void remove(Component component) {
list.remove(component);
}
}

public class 技术部 implements Component {
private List<Component> list = new ArrayList<>();

@Override
public void add(Component component) {
list.add(component);
}

@Override
public void remove(Component component) {
list.remove(component);
}
}

public class 餐厅 implements Component {
private List<Component> list = new ArrayList<>();

@Override
public void add(Component component) {
list.add(component);
}

@Override
public void remove(Component component) {
list.remove(component);
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
public static void main(String args[]) {
餐厅 总店 = 总店.getInstance();
总店.add(new 客服部());
总店.add(new 技术部());

餐厅 分店 = new 餐厅();
分店.add(new 客服部());
分店.add(new 技术部());

总店.add(分店);
}
}

桥接模式(Bridge)

把事物和其具体实现分开,使他们可以各自独立的变化。
老板想开发点餐软件,分为服务端和客户端,分别交给总店和分店的技术部实现。

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
public interface 点餐软件 {
void 开发软件();
}

public class 服务端软件 implements 点餐软件 {
@Override
public void 开发软件() {
System.out.println("开发服务端软件!");
}
}

public class 客户端软件 implements 点餐软件 {
@Override
public void 开发软件() {
System.out.println("开发客户端软件!");
}
}

public abstract class 点餐软件专项组 {
private 点餐软件 软件;

public void set软件(点餐软件 软件) {
this.软件 = 软件;
}

public void get软件() {
return this.一个软件;
}

public abstract void 开始开发();
}

public class 总店的技术部 extends 点餐软件专项组 {
public void 开始开发() {
System.out.println("总店开始安排人手!");
get软件().开发软件();
}
}

public class 分店的技术部 extends 点餐软件专项组 {
public void 开始开发() {
System.out.println("分店开始安排人手!");
get软件().开发软件();
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
点餐软件专项组 总店的专项组 = new 总店的技术部();
总店的专项组.set软件(new 服务端软件());
总店的专项组.开始开发();

点餐软件专项组 分店的专项组 = new 分店的技术部();
分店的专项组.set软件(new 客户端软件());
分店的专项组.开始开发();
}
}

外观模式(Facade)

避免几个类之间相互持有实例,将这几个类的实例放到同一个类中。
餐厅来了一个大客户,老板让一个大客户经理招待客户。

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
public class 司机 {
public void 开车() {
System.out.println("司机开车!");
}
}

public class 厨师 {
public void 做饭() {
System.out.println("厨师做饭!");
}
}

public class 技师 {
public void 搓澡() {
System.out.println("技师搓澡!");
}
}

public class 大客户经理 {
public void 招待客户() {
new 司机().开车();
new 厨师().做饭();
new 技师().搓澡();
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
new 大客户经理().招待客户();
}
}

享元模式(Flyweight)

将大量的小的重复使用的对象统一管理起来,避免用户多次创建重复对象造成的资源浪费。
大客户又来了,老板会优先安排上次的大客户经理,但是如果上次的大客户经理正忙,就会重新安排大客户经理招待客户。

1
2
3
4
5
6
7
8
9
10
11
public class 客服部 {
private Map<String, 大客户经理> map = new HashMap<>();

public 大客户经理 get大客户经理(String 大客户ID) {
大客户经理 指定大客户经理 = map.get(大客户ID);
if(指定大客户经理不存在 || 指定大客户经理正忙) {
指定大客户经理 = 重新安排大客户经理();
}
return 指定大客户经理;
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
new 客服部().get大客户经理(大客户ID).招待客户();
}
}

行为型

观察者模式(Observer)

当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化。
老板进行面试,面试结束后通知参与面试的人面试结果。

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
public interface 面试者 {
void 参加面试();
}

public class 校招人员 implements 面试者 {
@Override
public void 参加面试() {
System.out.println("校招人员参加面试");
}
}

public class 社招人员 implements 面试者 {
@Override
public void 参加面试() {
System.out.println("社招人员参加面试");
}
}

public interface 面试官 {
void add面试者(面试者 一个面试者);

void notify面试者(面试者 一个面试者);
}

public class 技术部面试官 Implememnts 面试官 {
private List<面试者> 所有面试者 = new ArrayList<>();

@Override
public void add面试者(面试者 一个面试者) {
所有面试官.add(一个面试官);
}

@Override
public void notify面试者(面试者 确定录用者) {
for(面试者 一个面试者 : 所有面试者) {
if(一个面试者.equals(确定录用者)) {
System.out.println("发Offer");
} else {
System.out.println("发未通过面试通知");
}
}
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Test {
public static void main(String[] args) {
面试官 一个面试官 = new 技术部面试官();

面试者 一个面试者 = new 校招人员();
一个面试官.add(一个面试者);
一个面试官.add(new 校招人员());
一个面试官.add(new 校招人员());
一个面试官.add(new 社招人员());

一个面试官.notify面试者(一个面试者);
}
}

访问者模式(Visitor)

封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
客人排队就餐,叫到号后可以进店就餐。

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
public interface 吃饭的地 {
void 有空位需带人(排队的人 客户);

void 服务员安排就餐位置(排队的人 客户);

void 制作食物(排队的人 客户);
}

public class 餐厅 implememnts 吃饭的地 {
@Override
public void 有空位需带人(排队的人 客户) {
客户.展示排队的号(this);
}

@Override
public void 服务员安排就餐位置(排队的人 客户) {
客户.点餐(this);
}

@Override
public void 制作食物(排队的人 客户) {
System.out.println("餐厅开始制作食物了");
}
}

public interface 排队的人 {
void 展示排队的号(吃饭的地 餐厅);

void 点餐(吃饭的地 餐厅);
}

public class 客户 implememnts 排队的人 {
public int 号码;

@Override
public 展示排队的号(吃饭的地 餐厅) {
餐厅.服务员安排就餐位置(this);
}

@Override
public 点餐(吃饭的地 餐厅) {
餐厅.制作食物(this);
}
}

public class 服务员 {
private List<排队的人> 列表 = new ArrayList<>();

private 吃饭的地 餐厅;

public 服务员(吃饭的地 餐厅) {
this.餐厅 = 餐厅;
}

public void add客户(排队的人 客户) {
列表.add客户(客户);
}

public void 开始叫号() {
for(排队的人 客户 : 列表) {
餐厅.有空位需带人(客户);
}
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
public class Test {
public static void main(String[] args) {
服务员 一个服务员 = new 服务员(new 餐厅());
一个服务员.添加排队的人(new 客户());
一个服务员.添加排队的人(new 客户());
一个服务员.添加排队的人(new 客户());

一个服务员.开始叫号();
}
}

迭代器模式(Iterator)

老板助理按照员工花名册依次叫员工去老板办公室领工资。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface 辅助老板发工资的人 {
void 看还有没有人没领工资();

void 叫员工去领工资();
}

public class 老板助理 implements 辅助老板发工资的人 {
private List<String> 员工花名册 = new ArrayList<>();

private int 当前叫过的人的数量 = 0;

public 老板助理(花名册 员工花名册) {
this.员工花名册 = 员工花名册;
}

public void 看还有没有人没领工资() {
return 当前叫过的人的数量 < 员工花名册上的人数;
}

public void 叫员工去领工资() {
System.out.println("叫员工去领工资!");
当前叫过的人的数量++;
}
}
  • 测试
1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
辅助老板发工资的人 老板助理 = new 老板助理(员工花名册);
while(老板助理.看还有没有人没领工资()) {
老板助理.叫员工去领工资();
}
}
}

模板方法模式(TemplateMethod)

开发软件前先确定架构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class 项目 {
@Override
public void 开始开发() {
确定架构();
System.out.println("开始开发");
}

public abstract void 确定架构();
}

public class 点餐软件 extends 项目 {
@Override
public void 确定架构() {
System.out.println("确定架构");
}
}
  • 测试
1
2
3
4
5
public class Test {
public static void main(String[] args) {
new 点餐软件().开始开发();
}
}

中介者模式(Mediator)

餐厅上线了外卖业务,订餐人向餐厅要一杯咖啡,餐厅委托骑手送咖啡。

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
public interface 平台 {
void 转发消息();

void set送餐者();
}

public class 外卖业务 implements 平台 {
private final 客户端 订餐者;
private 客户端 送餐者;

public 订单(客户端 订餐者) {
this.订餐者 = 订餐者;
订餐者.set订单(this);
}

@Override
public void set送餐者(客户端 送餐者) {
this.送餐者 = 送餐者;
送餐者.set订单(this);
}

@Override
public void 转发消息(String 消息, 客户端 用户) {
if(订餐者.equals(用户)) {
送餐者.接收消息(消息);
} else {
订餐者.接收消息(消息);
}
}
}

public class 客户端 {
private 平台 外卖平台;

public void set平台(平台 外卖平台) {
this.外卖平台 = 外卖平台;
}

public void 发送消息(String 消息) {
外卖平台.转发消息(消息, this);
}

public void 接收消息(String 消息) {
System.out.println("接收消息:" + 消息);
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
客户端 订餐者 = new 客户端();
客户端 送餐者 = new 客户端();

平台 外卖平台 = new 外卖业务(订餐者);
外卖平台.set送餐者(送餐者);

订餐者.发送消息("我要一杯咖啡");
送餐者.发送消息("已取,马上为您送到");
}
}

备忘录模式(Memento)

主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象。
老板规定分店每月保留10万用于平时开销,盈利部分划归总店,亏损部分总店补齐。

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
public class 餐厅 {
private 账上资金 资金;

private 分店每月分配额度 额度;

public 餐厅(long 初始金额) {
账上资金 = new 账上资金(初始金额);
额度 = new 分店每月分配额度(账上资金);
}

private void 买菜(long 金额) {
资金 -= 金额;
}

private void 卖菜(long 金额) {
资金 += 金额;
}

private void 月末结算() {
System.out.println("当月收支:" + (资金.get资金() - 额度.get额度()));
账上资金 = 额度.get额度();
}

public long get资金() {
return 资金.get资金();
}
}

public class 账上资金 {
private long 资金;

public 账上资金(long 资金) {
this.资金 = 资金;
}

public void 花钱(long 金额) {
this.资金 -= 金额;
}

public void 赚钱(long 金额) {
this.资金 += 金额;
}

public long get资金() {
return 资金;
}
}

public class 分店每月分配额度 {
private long 额度;

public 分店每月分配额度(账上资金 资金) {
this.额度 = 资金.get资金();
}

public long get额度() {
return 额度;
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
餐厅 分店 = new 餐厅(100000);

分店.买菜(1000);
分店.卖菜(1500);
分店.get资金();

分店.月末结算();
分店.get资金();
}
}

状态模式(State)

可以通过改变状态来获得不同的行为。
建立员工审批制度,员工先向直属上级发起审批请求,待审批通过后,再向店长发起审批请求。

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 interface 审批 {
void 决定是否通过审批(审批表 一个审批表);
}

public class 审批表 {
private 审批 审批流程 = new 部门经理审批();

public void 走审批流程() {
审批流程.决定是否通过审批(this);
}

public void 转到上级审批(审批 上级审批) {
审批流程 = 上级审批;
}

public 审批 get审批() {
return 审批流程;
}
}

public class 部门经理审批 implements 审批 {
@Override
public void 决定是否通过审批(审批表 一个审批表) {
System.out.println("部门经理通过审批");
一个审批表.转到上级审批(new 店长审批());
}
}

public class 店长审批 implements 审批 {
@Override
public void 决定是否通过审批(审批表 一个审批表) {
System.out.println("店长通过审批");
一个审批表.转到上级审批(null);
}
}
  • 测试
1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
审批表 一个审批表 = new 审批表();
while(一个审批表.get审批() != null) {
一个审批表.走审批流程();
}
}
}

策略模式(Strategy)

定义一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。
新店开业大酬宾,店长推出各种优惠活动:满200减50、老客户全单打9折、新客户全单打8折,优惠不能同时享。

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
public interface 优惠活动 {
float get帐单金额();
}

public class 账单 {
private float 原价;

private 优惠活动 一个优惠活动;

private 账单(float 原价) {
this.原价 = 原价;
}

public void set优惠活动(优惠活动 一个优惠活动) {
this.一个优惠活动 = 一个优惠活动;
}

public float get帐单金额() {
if(一个优惠活动 == null) {
return 原价;
} else {
return 一个优惠活动.get帐单金额();
}
}
}

public class 满20050 implements 优惠活动 {
private float 原价;

public20050(float 原价) {
this.原价 = 原价;
}

@Override
public float get帐单金额() {
return 原价 >= 200 ? 原价 - 50 : 原价;
}
}

public class 老客户全单打9折 implements 优惠活动 {
private float 原价;

public 老客户全单打9折(float 原价) {
this.原价 = 原价;
}

@Override
public float get帐单金额() {
return 原价 * 0.9f;
}
}

public class 新客户全单打8折 implements 优惠活动 {
private float 原价;

public 新客户全单打8折(float 原价) {
this.原价 = 原价;
}

@Override
public float get帐单金额() {
return 原价 * 0.8f;
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
public class Test {
public static void main(String[] args) {
账单 一个账单 = new 账单(100);
float 不参加优惠活动的金额 = 一个账单.get帐单金额();
float 参加满20050的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new20050(100)));
float 参加老客户全单打9折的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new 老客户全单打9折(100)));
float 参加新客户全单打8折的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new 新客户全单打8折(100)));
float 最优惠金额 = sort(不参加优惠活动的金额, 参加老客户全单打9折的金额, 参加老客户全单打9折的金额, 参加新客户全单打8折的金额);
}
}

职责链模式(ChainOfResponsibility)

将接受请求的对象连成一条线链并且沿着这条链传递请求,直到有一个对象能够处理它为止。
有记者来采访,找到了保安,保安知道自己不能接受采访,把记者带给保安队长,保安队长也知道自己不能接受采访,把记者带给店长。

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 abstract class 餐厅职员 {
protected 餐厅职员 上级管理者;

public void set上级管理者(餐厅职员 一个餐厅职员) {
this.上级管理者 = 一个管理者;
}

public void get上级管理者() {
return 上级管理者;
}

public abstract void 接受采访();
}

public class 保安 extends 餐厅职员 {
@Override
public void 接受采访() {
if (保安有接受采访权限) {
System.out.println("保安接受采访!");
} else if (有上级管理者) {
get上级管理者().接受采访();
}
}
}

public class 保安队长 extends 餐厅职员 {
@Override
public void 接受采访() {
if (保安队长有接受采访权限) {
System.out.println("保安队长接受采访!");
} else if (有上级管理者) {
get上级管理者().接受采访();
}
}
}

public class 店长 extends 餐厅职员 {
@Override
public void 接受采访() {
System.out.println("店长接受采访!");
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
public static void main(String[] args) {
餐厅职员 一个保安 = new 保安();
餐厅职员 一个保安队长 = new 保安队长();
餐厅职员 一个店长 = new 店长();

一个保安.set上级管理者(一个保安队长);
一个保安队长.set上级管理者(一个店长);

一个保安.接受采访();
}
}

命令模式(Command)

命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开。与责任链模式不同的是执行者是确定的,中途命令不能被处理,只能被传递。
又有记者来了,保安想起来上次是店长接受的采访,所以就知道了只要有记者来采访,就直接找店长。

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
public interface 预案 {
void 有记者来访();
}

public class 公关预案 implements 预案 {
private 店长 一个店长;

public 公关部(店长 一个店长) {
this.一个店长 = 一个店长;
}

@Override
public void 有记者来访() {
一个店长.接受采访();
}
}

public class 店长 {
public void 接受采访() {
System.out.println("店长接受采访!");
}
}

public class 保安 {
private 公关预案 一个公关预案;

public 保安(公关预案 一个公关预案) {
this.一个公关预案 = 一个公关预案;
}

public void 发现记者来了() {
一个公关预案.有记者来访();
}
}
  • 测试
1
2
3
4
5
6
7
8
public class CommandTest {
public static void main(String[] args) {
店长 一个店长 = new 店长();
公关预案 一个公关预案 = new 公关预案(一个店长);
保安 一个保安 = new 保安(一个公关预案);
一个保安.发现记者来了();
}
}

解释器模式(Interpreter)

在系统中如果某一特定类型的问题在频繁的发生,此时我们就有必要将这些问题的实例表述为一个语言中句子,因此可以构建一个解释器,然后利用该解释器来解释这些句子来解决这些问题。
两个记者分别来自不同的报社,一个是经济报社的,一个是美食报社的,虽然店长接受采访时和他们说了相同的内容,但是两个记者分别从两个角度完成了采访后稿件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface 采访的人 {
void 写采访后的稿件(采访的内容 一次采访的内容);
}

public class 经济报社记者 implements 采访的人 {
@Override
public void 写采访后的稿件(采访的内容 一次采访的内容) {
System.out.println("从经济角度写采访后的稿件!");
}
}

public class 美食报社记者 implements 采访的人 {
@Override
public void 写采访后的稿件(采访的内容 一次采访的内容) {
System.out.println("从美食角度写采访后的稿件!");
}
}
  • 测试
1
2
3
4
5
public class InterpreterTest {
public static void main(String[] args) {
new 美食报社记者().写采访后的稿件(店长接受采访时说的话);
}
}


设计模式
https://weichao.io/2cdd0c565e9c/
作者
魏超
发布于
2020年3月3日
更新于
2022年12月4日
许可协议