面对对象程序的设计准则
面对对象程序由对象组成, 对象包括数据和对数据进行操作的过程, 过程通常被称为方法或操作.
针对接口编程, 而不是针对实现编程,即往往我们不直接生成具体的类,而是先定义一个抽象类,让子类实现相应接口
优先使用对象组合, 而不是类继承。类继承导致父类的改动可能会影响所有能够追溯到此类的子类(如a继承b,b继承c,那么c的改动可能会影响a和b),并且继承嵌套越多,越难排查。
使用组合意味着往往一个大的复杂的对象可以合理的被拆分为可复用的多个小对象。
保证代码的松耦合,紧耦合的代码部分考虑使用中介者模式
创建型模式
创建型设计模式抽象了实例化过程。
Abstract Factory(抽象工厂)
意图
提供一个接口(结构中的 AbstractFactory)以创建一系列相关或互相依赖的对象,而无需指定它们具体的类。
结构
场景
考虑构建适应不同系统的UI界面,如Windows 7,Windows 10,macOS。
一个UI界面应当由许多基本的Widget(组件)构成,如Window(窗口)、ScrollBar(滚动条)等。
我们需要为不同系统的窗口、滚动条定义相应的外观和行为。
实现
// 对应 AbstractFactory
abstract class WidgetFactory {
abstract getWindow(): any;
abstract getScrollBar(): any;
}
// 对应 ConcreteFactory
class Win7WidgetFactory extends WidgetFactory {
private static Window: any;
private static ScrollBar: any;
getWindow() {
if (!Win7WidgetFactory.Window) {
Win7WidgetFactory.Window = {
// Window 实现
};
}
return Win7WidgetFactory.Window;
}
getScrollBar() {
// 同 createWindow
}
}
class Win10WidgetFactory extends WidgetFactory {
// 实现同 Win7WidgetFactory
}
// 对应 Client
class UI {
// 对应 AbstractProduct
Window: any;
ScrollBar: any;
constructor(widgetFactory: WidgetFactory) {
this.Window = widgetFactory.getWindow();
this.ScrollBar = widgetFactory.getScrollBar();
}
}
Builder(生成器)
意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
结构
场景
假设我们需要表示一条街道上的门面房。
那么我们最终应该得到一个Street(街道)实例,里面包含了我们需要的信息。
大部分情况下,我们需要Street实例表示出标准的信息,但是对于部分应用,我们仅需要Street实例表示出街道拥有的房子数量。
实现
// 对应 Builder
// 注意,这里没有用抽象类,而是使用空函数,这样子类就不需要重新定义用不到的接口
class StreetBuilder {
buildStreet() {
}
buildRoom() {
}
}
// 对应 ConcreteBuilder
class StandardStreetBuilder extends StreetBuilder {
buildStreet() {
// 具体实现
}
buildRoom() {
// 具体实现
}
getStreet() {
return {
// Street 对象
};
}
}
class CountingStreetBuilder extends StreetBuilder {
private roomCount = 0;
buildRoom() {
this.roomCount += 1;
}
getRoomCount() {
return this.roomCount;
}
}
// 对应 Director
class Street {
street: any;
// streetBuilder 为具体的 Builder,如 StandardStreetBuilder CountingStreetBuilder
constructor