0%

设计模式

常用的几个设计模式

1 Singleton

单例,一个类仅允许一个对象存在。例如一个虚拟机只有一个堆。

1.1 饿汉模式

1
2
3
4
5
6
7
8
9
class Demo {
Demo _singleton;
Demo() {}
public:
// 直接用static的成员变量也可以
Demo& singleton() {
return _singleton;
}
};

用语言初始化机制避免多线程多次构造对象的问题。只是在一开始就构造可能有点浪费?

1.2 懒汉模式

用到再构造(Lazy initialization)。注意多线程同步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Demo
{
private static readonly object _lock = new object();
private static Demo _singleton;
public static Demo Singleton
{
get
{
if (_singleton == null)
{
lock (_lock)
{
if (_singleton == null)
{
_singleton = new Demo();
}
}
}
return _singleton;
}
}
private Demo() { }
}

2 工厂模式

2.1 工厂方法模式

有一个抽象工厂、一个抽象产品,一堆产品。一个具体工厂生产一个具体产品。

这很OOP,符合开闭原则,用户只需要知道工厂,不需要知道具体产品是哪一个类。用的时候使用抽象产品(即只关心接口)

缺点是每添加一个产品就要加一个工厂。

2.2 抽象工厂

如果产品很多,特别是存在排列组合的情况,建议使用抽象工厂。

抽象工厂一个工厂可以生产一类产品(可以是不同的方法生产不同的产品)。这样在新增类型的时候才需要新工厂。

举个例子:

  1. 有两类抽象产品。键盘和鼠标.
  2. 抽象工厂,定义生产键盘和鼠标的接口
  3. 有Win鼠标、键盘,Mac鼠标、键盘四种具体产品
  4. Mac工厂和Win工厂,实现抽象工厂,生产Mac和Win的键盘和鼠标

3 观察者模式

观察者注册回调,在事件发生时invoke回调,通知观察者。

具体例子如MVVM的INotifyPropertyChanged

4 装饰器模式

  1. 有接口IBase
  2. A实现了接口IBase
  3. 装饰器Decorator实现了接口IBase,并且装饰器有一个局部变量A,装饰器选择性地将A的功能暴露,也可以修改、装饰A原有的功能,甚至增加新功能。

它的使用范围类似继承。但是装饰器相比继承提供了更高的可定制性。

在Java的系统库中

  • InputStream是抽象构建角色(Component)
  • ByteArrayInputStream、FileInputStream、StringBufferInputStream是具体构件角色(ConcreteComponent)
  • 由FilterInputStream、ObectInputStream是抽象装饰角色(Decorator)。它们实现了InputStream所规定的接口。
  • BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream是具体装饰角色(ConcreteDecorator)。