1、创建者模式
1-1、单例模式
1)饿汉式
关键点:实例在类的内部创建;
class Singleton {
constructor(options) {
if(!Singleton.instance) {
for(let name in options) {
if(options.hasOwnProperty(name)) {
this[name] = options[name]
}
}
Object.freeze(this)
Singleton.instance = this
}
return Singleton.instance
}
// methods
}
2)懒汉式
实际上,在javascript语言中,由每个对象都是唯一存在的实例,且函数是值,每个对象本身就是一个单例;
const singleton = {
key: value,
// 方法
method() {}
}
1-2、工厂模式
关键点:将对象的创建与使用分离;
可以分为:简单工厂模式、工厂方法模式、抽象工厂模式;
1-3、建造者模式
关键点:过程式地创建复杂对象,复杂使得对象的创建与表现分离;
复杂性:简单来说,实例属性很多的对象;对于这类对象,如果直接使用构造函数来创建,需要传入大量的参数;而且,很多情况下,有些参数不会被使用,这些未使用的参数会增加程序的复杂性;
class Room {
constructor() {
this.bed = null
this.dresser = null
this.wardrobe = null
this.bookcase = null
this.desk = null
this.chair = null
this.sofa = null
}
setBad(bed) {
this.bed = bed
}
setDresser(dresser) {
this.dresser = dresser
}
setWardrobe(wardrobe) {
this.wardrobe = wardrobe
}
setBookcase(bookcase) {
this.bookcase = bookcase
}
setDesk(desk) {
this.desk = desk
}
setChair(chair) {
this.chair = chair
}
setSofa(sofa) {
this.sofa = sofa
}
}
// 设置
class RoomBuilder {
constructor() {
this.room = new Room()
}
buildBed(bed) {
this.room.setBad(bed)
return this
}
buildDresser(dresser) {
this.room.setDresser(dresser)
return this
}
buildWardrobe(wardrobe) {
this.room.setWardrobe(wardrobe)
return this
}
buildBookcase(bookcase) {
this.room.setBookcase(bookcase)
return this
}
buildDesk(desk) {
this.room.setDesk(desk)
return this
}
buildChair(chair) {
this.room.setChair(chair)
return this
}
buildSofa(sofa) {
this.room.setChair(sofa)
return this
}
reset() {
this.room = new Room()
}
getRoom() {
const room = this.room
this.reset()
return room
}
}
// 指导构建过程
class Director {
constructor(builder) {
this.builder = builder
}
setBuilder(builder) {
this.builder = builder
}
constructBedRoom() {
return this.builder
.buildBed("2.4 * 2.0")
.buildDesk("silkwood")
.buildChair("game chair")
.getRoom()
}
}
2、结构型模式
结构型模式:关注如何有效地将都对象或类组合成复杂的结构;
1、适配器模式
思想:在接口不兼容的两个类(适配者与目标类)之间增加一层间接层(适配器),使适配者与目标类的接口相适应。
简单的例子:电源(Adaptee),笔记本电脑(Client)、电源适配器(Adapter)。
type Voltage = string
interface Target {
chargeFor20(): void
}
class Adapter implements Target {
constructor(private adaptee: Adaptee) {
this.adaptee = adaptee
}
chargeFor20() {
this.adaptee.convertTo20()
}
}
class Adaptee {
constructor(protected voltage: Voltage) {
this.voltage = voltage
}
chargeFor220() {
console.log(`当前输出电压是${this.voltage} V`)
}
convertTo20() {
console.log(`当前输出电压是20 V`)
}
}
class LaptopClient {
charge(target: Target) {
target.chargeFor20()
}
}
2、桥接模式
思想:一个类具有两个独立变化的维度;将两个维度进行分离,使它们都可以独立地变化;同时,在两个维度的抽象层上建立一个抽象关联(桥)来连接独立的继承结构;
关键点:桥是在抽象层(类)上建立的;JS没有接口或抽象类的概念,在实践中,更多是以函数式编程来体现这种设计思想;
简单的例子:带颜色的多边形;边数和颜色两个维度可独立变化;
interface Color {
log(): string;
}
abstract class Shape {
constructor(public color: Color) {
this.color = color;
}
logMe() {
console.log(`I am a ${this.color.log()} shape`)
}
}
// Create a Concrete Implementation
class Red implements Color {
log() {
return 'red';
}
}
class Blue implements Color {
log() {
return 'blue';
}
}
// Create a refined Abstraction that behaves slightly differently
class Circle extends Shape {
constructor(color: Color) {
super(color);
}
logMe() {
console.log(`I am a ${this.color.log()} circle.`);
}
}
class Triangle extends Shape {
constructor(color: Color) {
super(color);
}
}
3、组合模式
思想:将叶子组件和复合组件的公共方法抽离到抽象组件,客户端针对抽象组件进行编程 t 关键点:找出共同的属性和方法,定义抽象组件
interface Component {
name: string,
parent:Composite | null,
operation(): void,
detach(): void
}
class Leaf implements Component {
name: string,
parent?: Composite,
constructor(name: string) {
this.name = name
this.parent = null
}
operation() {
console.log(`Leaf: ${this.name}, Parent: ${this.parnet.name || 'none'}`)
}
detach() {
if(this.parent) this.parent.delete(this)
}
}
class Composite implements Component {
parent?: Composite,
compotents : Component[]
constructor(name: string) {
this.name = name
this.parent = null
this.components = []
}
operation() {
console.log(`Composite: ${this.name}, Parent: ${this.parnet.name || 'none'}, Components: ${this.components.length}`)
this.components.forEach(c => c.operation)
}
delete(name: string) {
const index = this.components.findIndex(c => c.name === name)
if(index > -1) this.components.splice(index, 1, 0)
}
detach() {
if(this.parent) this.parent.delete(this)
}
attach(component: Component) {
component.detach()
component.parent = this
this.components.push(component)
}
}