單例模式: 1、定義:單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱為單例類 2、實現過程要點: (1)單例類的構造函數為私有 (2)提供一個自身的靜態私有成員變數 (3)提供一個公有的靜態工廠方法 3、優點: (1)提供了對唯一實例的受控訪問 (2)由於在系統內 ...
單例模式:
1、定義:單例模式確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱為單例類
2、實現過程要點:
(1)單例類的構造函數為私有
(2)提供一個自身的靜態私有成員變數
(3)提供一個公有的靜態工廠方法
註:單例模式由類提供實例對象,所以需要使用 static 來定義方法和屬性,使我們可通過類名來調用函數獲取對象,
靜態域載入是在解析階段,而實例化是在初始化階段,所以靜態方法不能調用普通函數和屬性
3、優點:
(1)提供了對唯一實例的受控訪問
(2)由於在系統記憶體中只存在一個對象,因此可以節約系統資源
(3)允許可變數目的實例。我們可以基於單例模式進行擴展,使用與單例控制相似的方法來獲得指定個數的對象實例
4、缺點:
(1)單例模式中沒有抽象層,因此單例類的擴展有很大的困難
(2)單例類的職責過重,在一定程度上違背了“單一職責原則”
(3)濫用單例將帶來一些負面問題;如採用垃圾自動回收機制的語言,實例化的對象若長期未被使用,
則會被清除掉,下次要再使用該類則需重新實例化,而導致原來的狀態沒有了
5、適用環境:
(1)系統只需要一個實例對象
(2)客戶調用類的單個實例只允許使用一個公共訪問點,除了該公共訪問點,不能通過其他途徑訪問該實例
class Singleton1 { private static instance: Singleton1 = new Singleton1(); // 靜態私有成員變數 private constructor() {} // 私有構造函數,防止外部調用它生成其他實例 // 公有靜態工廠方法 static getInstance(): Singleton1 { return Singleton1.instance; } } const singleton_one: Singleton1 = Singleton1.getInstance(); const singleton_two: Singleton1 = Singleton1.getInstance(); console.log(singleton_one === singleton_two); // true
構建者模式:
1、定義:將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
2、模式結構:
(1)抽象建造者(Builder):包含創建產品各個子部件的抽象方法的介面,通常包含返回覆雜產品的方法
(2)具體建造者(ConcreteBuilder):實現 Builder 介面,完成複雜產品的各個部件的具體創建方法
(3)指揮者(Director):調用建造者對象中的部件構造與裝配方法完成複雜對象的創建
(4)產品角色(Product):包含多個組成部件的複雜對象,由具體建造者來創建其各個部件
3、優點:
(1)客戶端不必知道產品內部組成細節,將產品本身與產品的創建過程解耦
(2)每一個具體建造者都相對獨立,與其他具體建造者無關,用戶使用不同的具體建造者即可得到不同的產品對象
(3)可以更加精細地控制產品的創建過程
(4)增加新的具體建造者無須修改原有類的代碼,指揮者類對抽象建造者類編程,系統擴展方便,符合“開閉原則”
4、缺點:
(1)建造者模式所創建的產品一般具有較多的共同點,其組成部分相似,
如果產品之間的差異性很大,則不適合使用建造者模式,因此其使用範圍受到一定的限制
(2)如果產品的內部變化複雜,可能會導致需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大
5、適用場景:
(1)需要生成的產品對象有複雜的內部結構,這些產品對象通常包含多個成員屬性
(2)需要生成的產品對象的屬性相互依賴,需要指定其生成順序
(3)對象的創建過程獨立於創建該對象的類
(4)隔離複雜對象的創建和使用,並使得相同的創建過程可以創建不同的產品
// 產品角色 class Computer { private cpu: string; private mainBoard: string; private memory: string; private hardDisk: string; setCpu(cpu: string): void { this.cpu = cpu; } setMainBoard(mainBoard: string): void { this.mainBoard = mainBoard; } setMemory(memory: string): void { this.memory = memory; } setHardDisk(hardDisk: string):void { this.hardDisk = hardDisk; } getCpu(): string { return this.cpu; } getMainBoard(): string { return this.mainBoard; } getMemory(): string { return this.memory; } getHardDisk(): string { return this.hardDisk; } } // 抽象建造者 interface Builder { createCpu(cpu: string): void; createMainBoard(mainBoard: string): void; createMemory(memory: string): void; createHardDisk(hardDisk: string): void; createComputer(): Computer; } // 具體建造者 class ConcreteBuilder implements Builder { private computer: Computer = new Computer(); createCpu(cpu: string): void { this.computer.setCpu(cpu); } createMainBoard(mainBoard: string): void { this.computer.setMainBoard(mainBoard); } createMemory(memory: string): void { this.computer.setMemory(memory); } createHardDisk(hardDisk: string): void { this.computer.setHardDisk(hardDisk); } createComputer(): Computer { return this.computer; } } // 指揮者 class Director { private builder: Builder; constructor(builder: Builder) { this.builder = builder; } createComputer(cpu: string, mainBoard: string, memory: string, hardDisk: string): Computer { this.builder.createCpu(cpu); this.builder.createMainBoard(mainBoard); this.builder.createMemory(memory); this.builder.createHardDisk(hardDisk); return this.builder.createComputer(); } } let builder: Builder = new ConcreteBuilder(); let director: Director = new Director(builder); let computer: Computer = director.createComputer("i7", "Lenovo", "8G", "1T"); console.log(computer.getCpu()); // i7 console.log(computer.getMainBoard()); // Lenovo console.log(computer.getMemory()); // 8G console.log(computer.getHardDisk()); // 1T
原型模式:
1、定義:用原型實例指定創建對象的種類,並且通過復用這些原型創建新的對象
2、要點:
(1)通過克隆來創建新的對象實例
(2)為克隆出來的新的對象實例複製原型實例屬性的值
3、優點:
(1)可以在運行時動態根據原型生成新的種類的對象
(2)對客戶端隱藏具體的實現類型
4、缺點:
每個原型的子類都必須實現 clone 的操作,尤其是包含引用類型的對象時,克隆會比較麻煩
5、適用場景:
(1)對象之間相同或相似,即只是個別的幾個屬性不同的時候
(2)如對象的創建過程比較麻煩,但複製比較簡單的時候
// Prototype interface Clonable<T> { clone(): T; } // ConcretePrototype class Origin implements Clonable<Origin> { name: string; clone(): Origin { let target: Origin = new Origin(); target.name = this.name; return target; } } let orign: Origin = new Origin(); orign.name = "Lemon"; let cloneObj: Origin = orign.clone(); console.log(cloneObj.name); // Lemon