设计模式不是知识点,是一种经验的总结,用来解决某些场景下的某一类问题的通用解决方案。
设计模式让代码更容易被理解,确保了复用性、可靠性、可扩展性

设计原则

  • 单一职责原则:一个类,只有一个引起它变化的原因
  • 开闭原则:扩展开放,修改封闭
  • 里氏代替原则:子类必须替换掉它们的父类
  • 依赖倒置原则:面向接口编程,而不是面向实现编程
  • 接口隔离原则
  • 合成复用原则:Has-A 和 Is-A
  • 迪米特法则:不要和陌生人说话,最少知识原则

创建型模式

单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式

单例模式:

通过私有构造函数来保证类外部不能对类进行实例化,实现类只要一个实例。
创建一个返回类对象的静态方法,提供一个全局访问点。

*双重锁校验*

饿汉式(立即加载)、懒汉式(延迟加载)、生命周期托管
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 Singleton
{
private string name;

public string Name
{
get {
return name;
}
set {
name = value;
}
}

private static Singleton instance;

public Singleton(string name) {
this.name = name;
}

public static Singleton getSingleton(string name)
{
if (instance == null)
{
lock (typeof(Singleton))
{
if (instance == null)
{
instance = new Singleton(name);
}
}
}
return instance;
}
}

工厂方法模式:

声明一个工厂抽象类,定义一个工厂接口。
创建派生于工厂抽象类的产品抽象类和具体产品类,由其具体子类创建对象。
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
public abstract class Operation
{
public double NumberA { get; set; }
public double NumberB { get; set; }

public virtual double GetResult()
{
const double result = 0;
return result;
}
}

/// <summary>
/// 加法运算
/// </summary>
public class Plus : Operation
{
public override double GetResult()
{
return NumberA + NumberB;
}
}

/// <summary>
/// 减法运算
/// </summary>
public class Minus : Operation
{
public override double GetResult()
{
return NumberA - NumberB;
}
}

/// <summary>
/// 乘法运算
/// </summary>
public class Multiply : Operation
{
public override double GetResult()
{
return NumberA * NumberB;
}
}
/// <summary>
/// 除法运算
/// </summary>
public class Divide :Operation
{
public override double GetResult()
{
return NumberA / NumberB;
}
}

/// <summary>
/// 简单工厂
/// </summary>
public class OperationFactory
{
public static Operation CreateOperate(string operate)
{
Operation operation = null;
switch (operate)
{
case "+":
operation = new Plus();
break;
case "-":
operation = new Minus();
break;
case "*":
operation = new Multiply();
break;
case "/":
operation = new Divide();
break;
}
return operation;
}
}

//调用方法
Operation operateion = OperationFactory.CreateOperate("+");
operateion.NumberA = 10;
operateion.NumberB = 5;

Console.WriteLine(operateion.GetResult());

抽象工厂模式:

提供多个产品的抽象接口。
每一个具体工厂创建一个产品族中的多个产品对象,多个具体工厂就可以创建多个产品族中的多个对象。

建造者模式:

不要把产品的构造过程放在产品类中,而是由建造者类来负责构造过程,产品的内部表示放在产品类中。

原型工厂模式:

创建一个原型类,通过 MemberwiseClone() 实现浅拷贝

结构型模式

适配器模式:注重转换接口

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
public interface IBuddhistMonk
{
void 吃斋();
void 念佛();
void 打坐();
void 习武();
}

//适配器
public abstract class SpecialMonk : IBuddhistMonk
{
private string name;

public string Name
{
get { return name; }
set
{
name = value;
}
}

public SpecialMonk(string name) {
this.name = name;
}

public void 吃斋() { Console.WriteLine(name + "不吃斋"); }
public void 念佛() { Console.WriteLine(name + "不念佛"); }
public void 打坐() { Console.WriteLine(name + "不打坐"); }

public abstract void 习武();

public void 喝酒()
{
Console.WriteLine(name + "大口吃肉");
}
public void 吃肉()
{
Console.WriteLine(name + "大口喝酒");
}
}

public class OrdinaryMonk : IBuddhistMonk
{
private string name;

public string Name
{
get { return name; }
set
{
name = value;
}
}
public OrdinaryMonk(string name)
{
this.name = name;
吃斋();
念佛();
打坐();
习武();
}
public void 吃斋()
{
Console.WriteLine(Name + " 吃斋");
}
public void 念佛()
{
Console.WriteLine(Name + " 念佛");
}
public void 打坐()
{
Console.WriteLine(Name + " 打坐");
}
public void 习武()
{
Console.WriteLine(Name + " 习 “长拳”");
}

}

public class LuZhiShen : SpecialMonk
{
public LuZhiShen(string name) : base(name)
{
吃斋();
念佛();
打坐();
习武();
喝酒();
吃肉();
}

public override void 习武()
{
Console.WriteLine( Name + "习“横练功夫”");
}
}

public class WuSong : SpecialMonk
{
public WuSong(string name) : base(name)
{
习武();
喝酒();
吃肉();
}

public override void 习武()
{
Console.WriteLine(Name + "习“北派戳脚”");
}
}

装饰者模式:注重稳定接口
代理模式:注重假借接口
外观模式:注重简化接口

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
public class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" SubSystemOne Method");
}
}
public class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" SubSystemTwo Method");
}
}
//...其他子类

public class Facade
{
private SubSystemOne _one;
private SubSystemTwo _two;
//... 其他需要使用的类

public Facade()
{
//实例化
_one = new SubSystemOne();
_two = new SubSystemTwo();
}

public void MethodA()
{
Console.WriteLine("\nMethodA() ---- ");
_one.MethodOne();
_two.MethodTwo();
//...其他方法调用
}

public void MethodB()
{
Console.WriteLine("\nMethodB() ---- ");
_two.MethodTwo();
//...其他方法调用
}
}

//如何调用
Facade facade = new Facade();

facade.MethodA();
facade.MethodB();

桥接模式:注重分离接口和其实现
组合模式:注重统一接口
享元模式:注重保留接口

行为型模式

模板方法模式:

封装算法结构,定义算法骨架,支持算法子步骤变化

命令模式:

注重将请求封装为对象,支持请求的变化,通过将一组行为抽象为对象,实现行为请求者和行为实现者之间的解耦。

迭代器模式:

注重封装特定领域变化,支持集合的变化,屏蔽集合对象内部复杂结构,提供客户程序对它的透明遍历。

观察者模式:

注重封装对象通知,支持通信对象的变化,实现对象状态改变,通知依赖它的对象并更新。
  • 简单需求,水是否烧开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class BoilWater
{
public int waterTemperature = 0;
public void Boil()
{
for (int i = 0; i <= 100; i++)
{
waterTemperature = i;
Thread.Sleep(100);
if (waterTemperature == 100)
{
Call();
}
}
}
public void Call()
{
Console.Write("The Water is Boiled!");
}
}
  • 接口实现观察者模式
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
public class BoilWater
{
private int waterTemperature = 0;

/// <summary>
/// 主方法
/// </summary>
public void Boil()
{
for (int i = 0; i <= 100; i++)
{
waterTemperature = i;
Thread.Sleep(100);
Console.WriteLine("水当前温度:" + waterTemperature);
if (waterTemperature == 100)
{
if (Observers.Count != 0)
{
CallAllObserve();
}
else
{
DefaultCall();
}
}
}
}

/// <summary>
/// 默认处理方法
/// </summary>
private void DefaultCall()
{
Console.WriteLine("The Water is Boiled!");
}

/// <summary>
/// 存储接口列表方法循环调用
/// </summary>
private void CallAllObserve()
{
foreach (var item in Observers)
{
item.Run();
}
}

/// <summary>
/// 存储接口的列表
/// </summary>
public IList<RunInter> Observers = new List<RunInter>();

/// <summary>
/// 接口列表添加
/// </summary>
/// <param name="runner"></param>
public void AddObserve(RunInter runner)
{
Observers.Add(runner);
}

/// <summary>
/// 接口列表删除
/// </summary>
/// <param name="runner"></param>
public void RemoveObserve(RunInter runner)
{
Observers.Remove(runner);
}
}

/// <summary>
/// 定义接口
/// </summary>
public interface RunInter
{
void Run();
}

/// <summary>
/// 实现接口
/// </summary>
public class DoSomeThing : RunInter
{
public void Run()
{
Console.WriteLine("Do Other Things!");
}
}
public class DoOtherThing : RunInter
{
public void Run()
{
Console.WriteLine("The Water is Boiled!");
}
}

//如何调用
BoilWater boilWater = new BoilWater();

boilWater.AddObserve(new DoSomeThing());
boilWater.AddObserve(new DoOtherThing());

boilWater.Boil();
  • 委托和事件实现观察者模式
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
public class BoilWater
{
private int waterTemperature = 0;

/// <summary>
/// 主方法
/// </summary>
public void Boil()
{
for (int i = 0; i <= 100; i++)
{
waterTemperature = i;
Thread.Sleep(100);
Console.WriteLine("水当前温度:" + waterTemperature);
if (waterTemperature == 100)
{
if (Observers.Count != 0)
{
CallAllObserve();
CallAllObserve(new DoSomeThing("这是传参,接口方法调用!"));
}
if (actions != null)
{
actions();
}
else
{
DefaultCall();
}
}
}
}

/// <summary>
/// 默认处理方法
/// </summary>
private void DefaultCall()
{
Console.WriteLine("The Water is Boiled!");
}

/// <summary>
/// 存储接口列表方法循环调用
/// </summary>
private void CallAllObserve()
{
foreach (var item in Observers)
{
item.Run();
}
}
private void CallAllObserve(RunInter runner)
{
runner.Run();
}

/// <summary>
/// 存储接口的列表
/// </summary>
public IList<RunInter> Observers = new List<RunInter>();

/// <summary>
/// 接口列表添加
/// </summary>
/// <param name="runner"></param>
public void AddObserve(RunInter runner)
{
Observers.Add(runner);
}

/// <summary>
/// 接口列表删除
/// </summary>
/// <param name="runner"></param>
public void RemoveObserve(RunInter runner)
{
Observers.Remove(runner);
}

/// <summary>
/// 委托和事件实现观察者模式
/// </summary>
private event Action actions;

/// <summary>
/// 注册事件
/// </summary>
/// <param name="runner"></param>
public void AddObserve(Action runner)
{
actions += runner;
}
/// <summary>
/// 取消事件
/// </summary>
/// <param name="runner"></param>
public void RemoveObserve(Action runner)
{
actions -= runner;
}
}

/// <summary>
/// 定义接口
/// </summary>
public interface RunInter
{
void Run();
}

/// <summary>
/// 实现接口
/// </summary>
public class DoSomeThing : RunInter
{
private string _strInfo;
public void Run()
{
if (!string.IsNullOrEmpty(_strInfo))
{
Console.WriteLine("自定义字符串返回结果:" + _strInfo);
}
else
{
Console.WriteLine("Do Other Things!");
}
}

public DoSomeThing() { }

public DoSomeThing(string strInfo)
{
_strInfo = strInfo;
}
}
public class DoOtherThing : RunInter
{
public void Run()
{
Console.WriteLine("The Water is Boiled!");
}
}

//如何调用
BoilWater boilWater = new BoilWater();

boilWater.AddObserve(new DoSomeThing());
boilWater.AddObserve(new DoOtherThing());

boilWater.AddObserve(() =>
{
Console.WriteLine("注册事件 - 1");
});
boilWater.AddObserve(() =>
{
Console.WriteLine("注册事件 - 2");
});

boilWater.Boil();

中介者模式:

注重封装对象间的交互,通过封装一系列对象之间的复杂交互,使他们不需要显式相互引用,实现解耦。

状态模式:

注重封装与状态相关的行为,支持状态的变化,通过封装对象状态,从而在其内部状态改变时改变它的行为。

策略模式:

注重封装算法,支持算法的变化,通过封装一系列算法,从而可以随时独立于客户替换算法。

责任链模式:

注重封装对象责任,支持责任的变化,通过动态构建职责链,实现事务处理。

访问者模式:

注重封装对象操作变化,支持在运行时为类结构添加新的操作,在类层次结构中,在不改变各类的前提下定义作用于这些类实例的新的操作。

解释器模式:

注重封装特定领域变化,支持领域问题的频繁变化,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。

备忘录模式:

注重封装对象状态变化,支持状态保存、恢复。
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
// 观察者,外观模式
public delegate void PluginGeneralDelegate(string name, object[] parameters,
ref object result);

public delegate void PluginSiskinIndicatorDelegate(string name, object[] parameters,
ref object result);

public class PluginGlobalEvents
{
public static event PluginGeneralDelegate PluginGeneralInvoked;

/// <param name="name">方法名</param>
/// <param name="parameters">入参</param>
/// <returns>返回值</returns>
public static object PluginInvokeGeneral(string name, object[] parameters)
{
object result = null;
if (PluginGeneralInvoked != null)
PluginGeneralInvoked(name, parameters, ref result);
return result;
}

public static event PluginSiskinIndicatorDelegate PluginSiskinIndicatorInvoked;

/// <param name="name">方法名</param>
/// <param name="parameters">入参</param>
/// <returns>返回值</returns>
public static object PluginSiskinIndicator(string name, object[] parameters)
{
object result = null;
if (PluginSiskinIndicatorInvoked != null)
PluginSiskinIndicatorInvoked(name, parameters, ref result);
return result;
}
}

/// <summary>
/// 注册接口事件
/// </summary>
private void RegisterSiskinIndicatorEvens()
{
PluginGlobalEvents.PluginSiskinIndicatorInvoked += new PluginSiskinIndicatorDelegate(
delegate (string name, object[] parameters, ref object result)
{
switch (name)
{
case "GetFileContent":
{
string strDirectory = parameters[0] as string;
string strSubDirectory = parameters[1] as string;
string strFileName = parameters[2] as string;
result = GetFileContent(strDirectory, strSubDirectory, strFileName);
}
break;
case "SystemDateTime":
{
result = SystemDateTime;
}
break;
case "GetSubDirectories":
{
string strDirectory = parameters[0] as string;
result = GetSubDirectories(strDirectory);
}
break;
default:
break;
}
});
}