单例(Singleton)
模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
class Singleton {constructor(data) {if (Singleton.prototype.Instance === undefined) {this.data = data;Singleton.prototype.Instance = this;}return Singleton.prototype.Instance;}}
单例模式有 3 个特点:
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点;
原型(Prototype)
模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
ES6
class LoopImages {constructor(imgArr) {this.imgArr = imgArr;}createImage() {console.log(this.imgArr);}}class SlideLooImg extends LoopImages {constructor(imgArr) {super(imgArr);}changeImage() {console.log(this.imgArr);}}const test = new SlideLooImg('111');console.log(test.changeImage(),test.createImage());
工厂方法(Factory Method)
模式:定义一个用于创建产品的接口,由子类决定生产什么产品。定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点; 不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中, 避免依赖具体类,要绕过new 生成方式,
ES6
class User {constructor(type) {if (new.target === User) {throw new Error('抽象类不能实例化!')}this.type = type;}}class UserOfWechat extends User {constructor(name) {super('wechat');this.name = name;this.viewPage = ['首页', '通讯录', '发现页']}}class UserOfQq extends User {constructor(name) {super('qq');this.name = name;this.viewPage = ['首页', '通讯录', '发现页']}}class UserOfWeibo extends User {constructor(name) {super('weibo');this.name = name;this.viewPage = ['首页', '通讯录', '发现页']}}function getAbstractUserFactory(type) {switch (type) {case 'wechat':return UserOfWechat;break;case 'qq':return UserOfQq;break;case 'weibo':return UserOfWeibo;break;default:throw new Error('参数错误, 可选参数:superAdmin、admin、user')}}let WechatUserClass = getAbstractUserFactory('wechat');let QqUserClass = getAbstractUserFactory('qq');let WeiboUserClass = getAbstractUserFactory('weibo');
Typescript
工厂方法模式的主要优点有:
- 将要创建的对象,延迟到子类中,从而实现一种扩展策略
- 解决“单个对象”的需求变化点。
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
其缺点是:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
抽象工厂(AbstractFactory)
模式:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品,是面对多个产品等级结构,
ES6
class AbstractFactory {createImage() {}createLooImg(){}}class ConcreteFactory1 extends AbstractFactory {createImage() {return new LoopImages();}createLooImg() {return new SlideLooImg();}}class LoopImages {constructor() {}changeImage(){};createImage() {}}class SlideLooImg {constructor() {}changeImage(){};createImage() {}}const test = new ConcreteFactory1();console.log(test.createImage());
Typescript
interface Images {changeImage():any;createImage():any;}class LoopImages implements Images{constructor() {}changeImage() {};createImage() {}}class SlideLooImg implements Images{constructor() {}changeImage() {};createImage() {}}interface AbstractFactory {createImage():any;createLooImg():any;}class ConcreteFactory1 implements AbstractFactory {createImage() {return new LoopImages();}createLooImg() {return new SlideLooImg();}}const test = new ConcreteFactory1();
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
- 需要应对“多系列对象构建”(多个系列对象之间有关联、相互依赖)的需求变化,可考虑抽象工厂,
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码,满足开闭原则。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改
建造者(Builder)
模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。 由于需求变化,各个部分对象面临剧烈变化,但将它们组成的算法且十分稳定。
ES6
class Product {setPartA(partA) {this.partA = partA;}setPartB(partB) {this.partB = partB;}}class Builder {constructor() {this.product = new Product();}buildPartA() {this.product.setPartA('建造 partA');}buildPartB() {this.product.setPartB('建造 partB');}getResult() {return this.product}}class Director {constructor (builder) {this.builder = builder;}construct() {this.builder.buildPartA();this.builder.buildPartB();return this.builder.getResult();}}const builder = new Builder();const director = new Director(builder);console.log(director.construct());
Typescript
class Product {partA: string | undefined;partB:string | undefinedsetPartA(partA:string) {this.partA = partA;}setPartB(partB:string) {this.partB = partB;}}abstract class Builder {product: { setPartA(param:string): any;setPartB(param:string): any;};constructor() {this.product = new Product();}abstract buildPartA():any;abstract buildPartA(): any;getResult() {return this.product;}}class Builder1 extends Builder{constructor() {super();}buildPartA() {this.product.setPartA('建造 partA');}buildPartB() {this.product.setPartB('建造 partB');}}class Director {builder:anyconstructor (builder:any) {this.builder = builder;}construct() {this.builder.buildPartA();this.builder.buildPartB();return this.builder.getResult();}}const builder = new Builder1();const director = new Director(builder);console.log(director.construct());
该模式的主要优点如下:
- 各个具体的建造者相互独立,有利于系统的扩展。
- 客户端不必知道产品内部组成的细节,便于控制细节风险。
其缺点如下:
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,该模式会增加很多的建造者类。
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
