设计模式之JS

184 阅读2分钟

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)
    }
     
}