æ¨æè·ï¼éå¯ï¼ 大æ·å®ææ¯ 2023-07-17 18:02 åè¡¨äºæµæ±
æ¬ææ¨å¨ç³»ç»æ§ä»ç»ä¸ä¸23ç§è®¾è®¡æ¨¡å¼ï¼ç»åºéä¿ææçæ¡ä¾ãç»æå¾å代ç 示ä¾ï¼è¿ä¹æ¯æèªèº«å¦ä¹ çè§£çè¿ç¨ãæè®¸å ¶ä¸çå ç§è®¾è®¡æ¨¡å¼åç并䏿¯å¾æ¸ æ°æäºææï¼æ´è¯¦ç»ç坿 ¹æ®æå°çåèæç®è¿è¡æ·±å ¥å¦ä¹ ã
ä»ä¹æ¯è®¾è®¡æ¨¡å¼
设计模å¼è¿ä¸ªæ¦å¿µæ¯ç±ä¸æ¬å为ã设计模å¼ï¼å¯å¤ç¨é¢å对象软件çåºç¡ãç书æ¨å¹¿èæ¥ï¼è¿æ¬ä¹¦å¨1994å¹´ç±å个C++å·¥ç¨å¸ç¼åçãè¿æ¬ä¹¦æ¢è®¨äºé¢å对象çç¼ç¨çè½ååé·é±ï¼å¹¶ä»ç»äº23ç§å¯ä»¥ç¨æ¥è§£å³ç¼ç¨é®é¢ç模å¼ãè¿äºæ¨¡å¼å¹¶ä¸æ¯ç®æ³æè å ·ä½çå®ç°ï¼å®ä»¬æ´åæ¯æ³æ³ãè§ç¹åæ½è±¡ï¼è¾ 婿们å»è§£å³ä¸äºç¹å®é®é¢ã使¯è¿äºæ¨¡å¼å»ºç«å¨C++çOOPçåºç¡ä¹ä¸ï¼å½ä½¿ç¨æ´ç°ä»£çç¼ç¨è¯è¨å¦JavaScriptæ¶ï¼æ¨¡å¼å¯è½ä¸çæï¼çè³ç»ä»£ç æ·»å äºä¸å¿ è¦çéå¶ï¼ä½æ¯æä»¬ä»ç¶å¯ä»¥æè¿äºæ¨¡å¼å½åä¸äºç¼ç¨ç¥è¯æ¥å¦ä¹ äºè§£ãæä»¬å¦ä¹ 使ç¨è¿äºæ¨¡å¼çç®çæ¯å®ç°ä»£ç çé«å èåä½è¦åï¼æé«ä»£ç çå¤ç¨æ§ï¼è®©ä»£ç æ´å®¹æç被ä»äººç解并ä¿è¯ä»£ç çå¯é æ§ã
23ç§è®¾è®¡æ¨¡å¼ç®ä»
âå建åï¼Creationalï¼ï¼5ç§ï¼
æä¾åå»ºå¯¹è±¡çæºå¶ï¼ å¢å å·²æä»£ç ççµæ´»æ§åå¯å¤ç¨æ§ã
- å便¨¡å¼ï¼Singletonï¼
ä¿è¯ä¸ä¸ªç±»åªæä¸ä¸ªå®ä¾ï¼ å¹¶æä¾ä¸ä¸ªè®¿é®è¯¥å®ä¾çå ¨å±èç¹ã
- å忍¡å¼ï¼Prototypeï¼
å 许æä¸ä¸ªå¯¹è±¡ä½ä¸ºèå¾å建å¦ä¸ä¸ªå¯¹è±¡ï¼æ°å¯¹è±¡ç»§æ¿å对象ç屿§åæ¹æ³ã
- çæå¨æ¨¡å¼ï¼Builderï¼
åâæ¥éª¤âå建对象ã
- å·¥åæ¹æ³æ¨¡å¼ï¼Factory Methodï¼
æä¾åå»ºå¯¹è±¡çæ¥å£ï¼å¯¹è±¡è¢«å建åå¯ä»¥ä¿®æ¹ã
- æ½è±¡å·¥å模å¼ï¼Abstract Factoryï¼
å 许å¨ä¸æå®å ·ä½ç±»çæ åµä¸çæä¸ç³»åç¸å ³ç对象ã
âç»æåï¼Structuralï¼ï¼7ç§ï¼
ä»ç»å¦ä½å°å¯¹è±¡åç±»ç»è£ æè¾å¤§çç»æï¼ å¹¶åæ¶ä¿æç»æççµæ´»å髿ã
- æ¡¥æ¥æ¨¡å¼ï¼Bridgeï¼
å°æ½è±¡é¨åä¸å®çå®ç°é¨åå离ï¼ä½¿å®ä»¬é½å¯ä»¥ç¬ç«å°ååã
- å¤è§æ¨¡å¼ï¼Facadeï¼
ç»åºãæ¡æ¶ä»¥åå ¶ä»å¤æçç±»éæä¾ç®åçæ¥å£ã
- ç»å模å¼ï¼Compositeï¼
å°å¯¹è±¡ç»åææ å½¢ç»ææ¥è¡¨ç°æ´ä½åé¨åç屿¬¡ç»æ
- è£ é¥°å¨æ¨¡å¼ï¼Decoratorï¼
éè¿å¢å ä¸ä¸ªä¿®é¥°å¯¹è±¡æ¥å è£¹åæ¥ç对象ï¼ä»èç»åæ¥çå¯¹è±¡æ·»å æ°çè¡ä¸º
- éé 卿¨¡å¼ï¼Adapterï¼
å 许两个æ¥å£ä¸å ¼å®¹ç对象ç¸äºäº¤äº
- ä»£çæ¨¡å¼ï¼Proxyï¼
为å¦ä¸ä¸ªå¯¹è±¡æä¾æ¿ä»£æè å ä½ç¬¦
- äº«å æ¨¡å¼ï¼Flyweightï¼
è¿ç¨å ±äº«ææ¯æ¥ææå°æ¯æå¤§éç»ç²åº¦å¯¹è±¡çå¤ç¨ï¼ä»¥åå°å建çå¯¹è±¡çæ°é
âè¡ä¸ºåï¼Behavioralï¼ï¼11ç§ï¼
è´è´£å¯¹è±¡é´ç髿æ²éåèè´£å§æ´¾ã
- è¿ä»£å¨æ¨¡å¼ï¼Iteratorï¼
ç¨äºéåéåçå ç´
- è§£é卿¨¡å¼ï¼Interpreter ï¼
ç»å®ä¸ä¸ªè¯è¨, å®ä¹å®çææ³çä¸ç§è¡¨ç¤ºï¼å¹¶å®ä¹ä¸ä¸ªè§£éå¨, 该解éå¨ä½¿ç¨è¯¥è¡¨ç¤ºæ¥è§£éè¯è¨ä¸çå¥å
- è§å¯è 模å¼ï¼Observerï¼
å®ä¹ä¸ä¸ªè®¢é æºå¶æ¥éç¥å¤ä¸ªå¯¹è±¡å®ä»¬å¨è§å¯ç对象åççä»»ä½äºä»¶
- ä¸ä»è 模å¼ï¼Mediatorï¼
ç¨ä¸ä¸ªä¸ä»å¯¹è±¡æ¥å°è£ å¤ä¸ªå¯¹è±¡ä¹é´çå¤æäº¤äº
- 访é®è 模å¼ï¼Visitorï¼
é对äºå¯¹è±¡ç»æä¸çå ç´ ï¼å®ä¹å¨ä¸æ¹å该对象çåæä¸è®¿é®å ¶ç»æä¸å ç´ çæ°æ¹æ³ã
- ç¶ææ¨¡å¼ï¼Stateï¼
å½ä¸ä¸ªå¯¹è±¡çå é¨ç¶æåçæ¹åæ¶ï¼ä¼å¯¼è´å ¶è¡ä¸ºçæ¹åï¼è¿çèµ·æ¥åæ¯æ¹åäºå¯¹è±¡
- å¤å¿å½æ¨¡å¼ï¼Mementoï¼
å 许å¨ä¸æ´é²å¯¹è±¡å®ç°ç»èçæ åµä¸ä¿å忢å¤å¯¹è±¡ä¹åçç¶æã
- çç¥æ¨¡å¼ï¼Strategyï¼
å®ä¹ä¸ç³»åçç®æ³ï¼æå®ä»¬ä¸ä¸ªä¸ªå°è£ èµ·æ¥ï¼å¹¶ä¸ä½¿å®ä»¬å¯ä»¥ç¸äºæ¿æ¢ã
- æ¨¡æ¿æ¹æ³æ¨¡å¼ï¼Template Methodï¼
ç¶ç±»ä¸å®ä¹ä¸ç»æä½ç®æ³éª¨æ¶ï¼èå°ä¸äºå®ç°æ¥éª¤å»¶è¿å°åç±»ä¸ï¼ä½¿å¾åç±»å¯ä»¥ä¸æ¹åç¶ç±»çç®æ³ç»æçåæ¶ï¼éæ°å®ä¹ç®æ³ä¸çæäºå®ç°æ¥éª¤ã
- èè´£é¾æ¨¡å¼ï¼Chain of Responsibilityï¼
å°è¯·æ±éè¿å¤çé¾ä¼ éï¼é¾æ¡ä¸çæ¯ä¸ä¸ªå¤çç¨åºå³å®è¦ä¹å¤ç请æ±ï¼è¦ä¹å°è¯·æ±ä¼ éç»é¾æ¡ä¸çä¸ä¸ä¸ªå¤çç¨åºã
- å½ä»¤æ¨¡å¼ï¼Commandï¼
å°è¯·æ±ä»¥å½ä»¤çå½¢å¼å 裹å¨å¯¹è±¡ä¸ï¼å¹¶ä¼ ç»è°ç¨å¯¹è±¡ãè°ç¨å¯¹è±¡å¯»æ¾å¯ä»¥å¤ç该å½ä»¤çåéç对象ï¼å¹¶æè¯¥å½ä»¤ä¼ ç»ç¸åºç对象ï¼è¯¥å¯¹è±¡æ§è¡å½ä»¤ã
设计模å¼ç»è§£
âå建å
åå»ºåæ¨¡å¼æä¾äºåå»ºå¯¹è±¡çæºå¶ï¼ è½å¤æåå·²æä»£ç ççµæ´»æ§åå¯å¤ç¨æ§ã
- å便¨¡å¼
å便¨¡å¼æ¯ä¸ç§å建å设计模å¼ï¼å®ä¿è¯ä¸ä¸ªç±»åªæä¸ä¸ªå®ä¾ï¼ å¹¶æä¾ä¸ä¸ªè®¿é®è¯¥å®ä¾çå ¨å±èç¹ã
举个ç°å®çä¾åï¼æ¯å¦ä¸ä¸ªå½å®¶åªæä¸ä¸ªå®æ¹æ¿åºãä¸ç®¡ç»ææ¿åºçæ¯ä¸ªäººç身份æ¯ä»ä¹ï¼ âææ¿åºâ è¿ä¸ç§°è°æ»æ¯é´å«é£äºææè çå ¨å±è®¿é®èç¹ã
å便¨¡å¼ç»æï¼
代ç å®ç°ï¼
class Singleton {
constructor() {
this.instance = null; // å便¨¡å¼çæ è¯
}
getInstance() {
if (!this.instance) {
this.instance = new Singleton(name);
}
return this.instance;
}
}
function clientCode() {
const s1 = Singleton.getInstance();
const s2 = Singleton.getInstance();
if (s1 === s2) {
console.log('åä¸ä¸ªå®ä¾');
} else {
console.log('ä¸åå®ä¾');
}
}
clientCode(); // åä¸ä¸ªå®ä¾
- å忍¡å¼
å忍¡å¼ä¸ç§å建å设计模å¼ï¼ å®è½å¤å¤å¶å·²æå¯¹è±¡ï¼è·ååæå¯¹è±¡ç屿§åæ¹æ³ï¼èåæ é使代ç ä¾èµå®ä»¬æå±çç±»ã
举个ç°å®çä¾åï¼æ¯å¦ç»èçæä¸åè£ãæä¸åè£ä¼äº§çä¸å¯¹å®å ¨ç¸åçç»èãåå§ç»èå°±æ¯ä¸ä¸ªååï¼ å®å¨å¤å¶ä½ççæè¿ç¨ä¸èµ·å°äºæ¨å¨ä½ç¨ã
å忍¡å¼ç»æï¼
代ç å®ç°ï¼
class Prototype {
constructor(name) {
this.name = name;
}
setName(name) {
this.name = name;
}
clone() {
return new Prototype(this.name);
}
}
function clientCode() {
const p1 = new Prototype('å忍¡å¼');
const p2 = p1.clone();
if(p1.name === p2.name) {
console.log('屿§å¤å¶æå');
}
p2.setName('å¤å¶çå忍¡å¼')ï¼
if(p2.name === 'å¤å¶çå忍¡å¼') {
console.log('æ¹æ³å¤å¶æåï¼å¹¶ä¸ä¾èµäºåå
çç±»');
}
}
clientCode(); // 屿§å¤å¶æå æ¹æ³å¤å¶æåï¼å¹¶ä¸ä¾èµäºåå
çç±»
- çæå¨æ¨¡å¼
æé 卿¨¡å¼æ¯ä¸ç§å建å设计模å¼ï¼ å®è½å¤åæ¥éª¤åå»ºå¤æå¯¹è±¡ï¼å¯ä»¥ä½¿ç¨ç¸åçå建代ç çæä¸åç±»ååå½¢å¼ç对象ã
举个ç°å®çä¾åï¼æ¯å¦æ±½è½¦çå¶é ï¼Aå·¥åç产轮èï¼Bå·¥åç产车é¨ï¼Cå·¥åç产ç»çï¼... æç»Zå·¥åè´è´£ç»è£ è¿äºé¶ä»¶ï¼åºåä¸è¾å®æ´ç汽车ã
çæå¨æ¨¡å¼ç»æï¼
ç®èè¨ä¹ï¼çæå¨æ¨¡å¼å¯ä»¥æ¦æ¬ä¸ºä¸¤é¨åï¼ç¬¬ä¸é¨åæ¯å ·ä½çæå¨ï¼ConcreteBuilderï¼è´è´£new Productï¼å¹¶æä¾å¤çProductçåç§æ¹æ³ï¼ç¬¬äºé¨å主管ï¼Directorï¼è´è´£å¤çProductçåç§æ¹æ³çè°ç¨ã
代ç å®ç°ï¼
interface Builder { // æå®å建product对象ä¸åé¨åçæ¹æ³
producePartA(): void;
producePartB(): void;
producePartC(): void;
}
// è¦å建ç产å
class Product {
public parts: string[] = [];
public listParts(): void {
console.log(`Product parts: ${this.parts.join(', ')}\n`);
}
}
// å
·ä½çæå¨1
class ConcreteBuilder implements Builder {
private product: Product1; // 空ç产å对象ï¼ç¨äºåç»çç»è£
constructor() {
this.reset();
}
public reset(): void {
this.product = new Product();
}
// ææçç产æ¥éª¤é½æ¯å¯¹åä¸ä¸ªproductå®ä¾è¿è¡æä½
public producePartA(): void {
this.product.parts.push('PartA1');
}
public producePartB(): void {
this.product.parts.push('PartB1');
}
public producePartC(): void {
this.product.parts.push('PartC1');
}
// è·å产åçæ¹æ³
public getProduct(): Product {
const result = this.product;
this.reset(); // è°ç¨éç½®æ¹æ³ï¼å好ç产ä¸ä¸ä¸ªäº§åçåå¤ï¼ä½è¿å¹¶ä¸æ¯å¿
é¡»ç
return result;
}
}
// å®ä¹å建æ¥éª¤çæ§è¡é¡ºåº, å
¶ä¸çæå¨è´è´£æä¾è¿äºæ¥éª¤çå®ç°ã
class Director {
private builder: Builder;
public setBuilder(builder: Builder): void {
this.builder = builder;
}
public buildMinimalViableProduct(): void {
this.builder.producePartA();
}
public buildFullFeaturedProduct(): void {
this.builder.producePartA();
this.builder.producePartB();
this.builder.producePartC();
}
}
// 客æ·ç«¯ä»£ç
function clientCode(director: Director) {
const builder = new ConcreteBuilder();
director.setBuilder(builder); // å°ä¸»ç®¡ç±»ä¸å
·ä½çæå¨è¿è¡å
³è
console.log('çæä¸ä¸ªåºç¡äº§å:');
director.buildMinimalViableProduct();
builder.getProduct().listParts(); // Product parts: PartA1
console.log('çæä¸ä¸ªå®æ´äº§å:');
director.buildFullFeaturedProduct();
builder.getProduct().listParts(); // Product parts: PartA1, PartB1, PartC1
// builderç±»ä¹å¯ä»¥ä¸ä¾èµäºDirectorï¼å¯ä»¥ç´æ¥è°ç¨å
¶å
é¨çæ¹æ³
console.log('çæå
¶ä»å®å¶äº§å:');
builder.producePartA();
builder.producePartC();
builder.getProduct().listParts(); // Product parts: PartA1, PartC1
}
const director = new Director();
clientCode(director);
- å·¥åæ¹æ³æ¨¡å¼
å·¥åæ¹æ³æ¨¡å¼æ¯ä¸ç§å建å设计模å¼ï¼ å ¶å¨ç¶ç±»ä¸æä¾ä¸ä¸ªåå»ºå¯¹è±¡çæ¹æ³ï¼ å 许åç±»å³å®å®ä¾å对象çç±»åã
å·¥åæ¹æ³æ¨¡å¼ç»æï¼
代ç å®ç°ï¼
interface Product { // 声æäºææäº§åå¿
é¡»å®ç°çæä½
operation(): string;
}
// å建è
ç±»ï¼å£°æè¿å产å对象ç工忹æ³
abstract class Creator {
public abstract factoryMethod(): Product;
public someOperation(): string {
const product = this.factoryMethod(); // è°ç¨å·¥åæ¹æ³å建ä¸ä¸ªäº§å对象
return `Creator: åä¸ä¸ªCreatorç代ç 被åºç¨å¨ ${product.operation()}`;
}
}
// å
·ä½å建è
å°éå工忹æ³ï¼ä»¥æ¹åå
¶æè¿åç产åç±»å
class ConcreteCreator1 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct1();
}
}
class ConcreteCreator2 extends Creator {
public factoryMethod(): Product {
return new ConcreteProduct2();
}
}
// å
·ä½äº§åéæä¾äº§åæ¥å£çåç§å®ç°
class ConcreteProduct1 implements Product {
public operation(): string {
return '{ConcreteProduct1çç»æ}';
}
}
class ConcreteProduct2 implements Product {
public operation(): string {
return '{ConcreteProduct2çç»æ}';
}
}
// 客æ·ç«¯ä»£ç
function clientCode(creator: Creator) {
console.log(creator.someOperation());
}
console.log('App: ConcreteCreator1 å¯å¨');
clientCode(new ConcreteCreator1());
//Creator: åä¸ä¸ªCreatorç代ç 被åºç¨å¨ {ConcreteProduct1çç»æ}
console.log('App: Launched with the ConcreteCreator2.');
clientCode(new ConcreteCreator2());
//Client: I'm not aware of the creator's class, but it still works.
// Creator: åä¸ä¸ªCreatorç代ç 被åºç¨å¨ {ConcreteProduct2çç»æ}
ç®èè¨ä¹ï¼å®¢æ·ç«¯ä¼ å ¥çæ¯å ·ä½çæå¨ï¼ç¶åå建åºä¸ä¸ªæ°ååï¼ä¸åçå ·ä½çæå¨å¯ä»¥äº§åºä¸åçå ·ä½ååãä¹å°±æ¯ç¶ç±»ä¸æä¾ä¸ä¸ªåå»ºå¯¹è±¡çæ¹æ³ï¼ å 许åç±»å³å®å®ä¾å对象çç±»åã
- æ½è±¡å·¥å模å¼
æ½è±¡å·¥åæ¨¡å¼æ¯ä¸ç§å建å设计模å¼ï¼ å®è½å建ä¸ç³»åç¸å ³çå¯¹è±¡ï¼ èæ éæå®å ¶å ·ä½ç±»ã
æ½è±¡å·¥å模å¼ç»æï¼
代ç å®ç°ï¼
// æ½è±¡å·¥åæ¥å£ï¼å£°æå¯è¿åä¸åæ½è±¡äº§åçæ¹æ³
interface AbstractFactory {
createProductA(): AbstractProductA;
createProductB(): AbstractProductB;
}
// æ½è±¡äº§åæ¥å£
interface AbstractProductA {
usefulFunctionA(): string;
}
interface AbstractProductB {
usefulFunctionB(): string;
anotherUsefulFunctionB(collaborator: AbstractProductA): string;
}
// å
·ä½å·¥å å¯çæå±äºåä¸åä½çç³»å产å
class ConcreteFactory1 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
// å
·ä½äº§å ç±ç¸åºçå
·ä½å·¥åå建
class ConcreteProductA1 implements AbstractProductA {
public usefulFunctionA(): string {
return 'è¿éæ¯A1产å';
}
}
class ConcreteProductA2 implements AbstractProductA {
public usefulFunctionA(): string {
return 'è¿éæ¯A2产å';
}
}
class ConcreteProductB1 implements AbstractProductB {
public usefulFunctionB(): string {
return 'è¿éæ¯B1产å';
}
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `è¿éæ¯B1产ååä½ (${result})`;
}
}
class ConcreteProductB2 implements AbstractProductB {
public usefulFunctionB(): string {
return 'è¿éæ¯B2产å';
}
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `è¿éæ¯B2产ååä½ (${result})`;
}
}
// 客æ·ç«¯ä»£ç ä»
éè¿æ½è±¡ç±»åAbstractFactory使ç¨å·¥åå产å
function clientCode(factory: AbstractFactory) {
const productA = factory.createProductA();
const productB = factory.createProductB();
console.log(productB.usefulFunctionB());
console.log(productB.anotherUsefulFunctionB(productA));
}
clientCode(new ConcreteFactory1()); // è¿éæ¯B1产å // è¿éæ¯B1产ååä½ï¼A1ï¼
clientCode(new ConcreteFactory2()); // è¿éæ¯B2产å // è¿éæ¯B2产ååä½ï¼A2ï¼
ç®èè¨ä¹ï¼å®¢æ·ç«¯çå ¥åæ¯å ·ä½å·¥å(å ·ä½å·¥åæ¯æ½è±¡å·¥åçå®ç°)ï¼å ·ä½å·¥åä¼çæå ·ä½äº§åãæ½è±¡å·¥åä¸ºä½ æä¾äºä¸ä¸ªæ¥å£ï¼ å¯ç¨äºå建æ¯ä¸ªç³»å产åç对象ãåªè¦ä»£ç éè¿è¯¥æ¥å£åå»ºå¯¹è±¡ï¼ é£ä¹ä½ å°±ä¸ä¼çæä¸åºç¨ç¨åºå·²çæç产åç±»åä¸ä¸è´ç产åã
âç»æå
ç»æåæ¨¡å¼ä»ç»å¦ä½å°å¯¹è±¡åç±»ç»è£ æè¾å¤§çç»æï¼ å¹¶åæ¶ä¿æç»æççµæ´»å髿ã
- æ¡¥æ¥æ¨¡å¼
æ¡¥æ¥æ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ å¯å°ä¸ä¸ªå¤§ç±»æä¸ç³»åç´§å¯ç¸å ³çç±»æå为ä¸åç屿¬¡ç»æï¼ ä»èè½å¨å¼åæ¶åå«ä½¿ç¨ã
æ¡¥æ¥æ¨¡å¼ç»æï¼
代ç å®ç°ï¼
// å®ä¹äºææImplementationç±»çæ¥å£
interface Implementation {
operationImplementation(): string;
}
class Abstraction {// æä¾å¯¹Implementationçå¼ç¨ï¼å¹¶å°ææçå®é
å·¥ä½å§æç»å®
protected implementation: Implementation;
constructor(implementation: Implementation) {
this.implementation = implementation;
}
public operation(): string {
const result = this.implementation.operationImplementation();
return `æ½è±¡é¨å: åºç¡æä½: ${result}`;
}
}
// å¨ä¸æ¹åImplementationç±»çåæä¸ç»§æ¿Abstraction
class ExtendedAbstraction extends Abstraction {
public operation(): string {
const result = this.implementation.operationImplementation();
return `ç»§æ¿çæ½è±¡é¨å: ç»§æ¿çæä½:${result}`;
}
}
class ConcreteImplementationA implements Implementation {
public operationImplementation(): string {
return 'å
·ä½å®ç°A: è¿éæ¯Açç»æ';
}
}
class ConcreteImplementationB implements Implementation {
public operationImplementation(): string {
return 'å
·ä½å®ç°B: è¿éæ¯Bçç»æ';
}
}
// 客æ·ç«¯ä»£ç
function clientCode(abstraction: Abstraction) {
console.log(abstraction.operation());
}
let implementation = new ConcreteImplementationA();
let abstraction = new Abstraction(implementation);
clientCode(abstraction); // æ½è±¡é¨å:åºç¡æä½:å
·ä½å®ç°A: è¿éæ¯Açç»æ.
implementation = new ConcreteImplementationB();
abstraction = new ExtendedAbstraction(implementation);
clientCode(abstraction); // ç»§æ¿çæ½è±¡é¨å: ç»§æ¿çæä½: å
·ä½å®ç°B: è¿éæ¯Bçç»æ.
ç®åæ¥è¯´ï¼å¯¹äºä¸ä¸ªå¤æåºå¤§çç³»ç»ï¼å¯ä»¥å°å ¶åå±ï¼ç¬¬ä¸å±æ¯æ½è±¡å±ï¼ç¬¬äºå±ä¸ºå ·ä½å±ï¼æ½è±¡å±å¯ä»¥æå¯¹èªå·±çè°ç¨å§æ´¾ç»å®ç°å±å®ç°ï¼èææçå®ç°å±é½å ·æç»ä¸æ¥å£ï¼æä»¥å®ç°å±å¯ä»¥å¨æ½è±¡é¨åå é¨è¿è¡ç¸äºæ¿æ¢ã
- å¤è§æ¨¡å¼
å¤è§æ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ è½ä¸ºç¨åºåºã æ¡æ¶æå ¶ä»å¤æç±»æä¾ä¸ä¸ªç®åçæ¥å£ã
举个ç°å®çä¾åï¼æ·å®å°±æ¯ä¸ä¸ªå¤è§ï¼å®æä¾äºä½ è´ç©ãæ¯ä»ãéè±ä¸é¨çæ¥å£ã
å¤è§æ¨¡å¼ç»æï¼
代ç å®ç°ï¼
// 为ä¸ä¸ªæå¤ä¸ªåç³»ç»ç夿é»è¾æä¾ç®åæ¥å£
class Facade {
protected subsystem1: Subsystem1;
protected subsystem2: Subsystem2;
constructor(subsystem1?: Subsystem1, subsystem2?: Subsystem2) {
this.subsystem1 = subsystem1 || new Subsystem1();
this.subsystem2 = subsystem2 || new Subsystem2();
}
public operation(): string {
let result = 'Facadeåå§ååç³»ç»';
result += this.subsystem1.operation1();
result += this.subsystem2.operation1();
result += 'Facadeå½ä»¤åç³»ç»æ§è¡æä½';
result += this.subsystem1.operationN();
result += this.subsystem2.operationZ();
return result;
}
}
class Subsystem1 {
public operation1(): string {
return 'Subsystem1åå¤å¥½äº!';
}
public operationN(): string {
return 'Subsystem1æ§è¡!';
}
}
class Subsystem2 {
public operation1(): string {
return 'Subsystem2åå¤å¥½äº';
}
public operationZ(): string {
return 'Subsystem2æ§è¡!';
}
}
// 客æ·ç«¯ä»£ç
function clientCode(facade: Facade) {
console.log(facade.operation());
}
const subsystem1 = new Subsystem1();
const subsystem2 = new Subsystem2();
const facade = new Facade(subsystem1, subsystem2);
clientCode(facade); // Facadeåå§ååç³»ç» Subsystem1åå¤å¥½äº! Subsystem2åå¤å¥½äº Facadeå½ä»¤åç³»ç»æ§è¡æä½ Subsystem1æ§è¡! Subsystem2æ§è¡!
- ç»å模å¼
ç»åæ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ ä½ å¯ä»¥ä½¿ç¨å®å°å¯¹è±¡ç»åææ ç¶ç»æï¼ å¹¶ä¸è½å使ç¨ç¬ç«å¯¹è±¡ä¸æ ·ä½¿ç¨å®ä»¬ã
举个ç°å®çä¾åï¼æ¯å¦å¦æ ¡ï¼å¦æ ¡ç±å¹´çº§ç»æï¼å¹´çº§ç±ççº§ç»æï¼ç级ç±å¦ç个ä½ç»æãå½å¦æ ¡ä¸è¾¾éè¦éç¥æ¶ï¼æ¯é级ä¸åçï¼éè¿ä¸ä¸ªä¸ªå±çº§çä¼ éï¼ç´å°æ¯ä¸ªå¦ç齿¥æ¶å°éç¥ã
ç»å模å¼ç»æï¼
代ç 示ä¾ï¼
// æè¿°äº ç®å å 夿 æå
±æçæä½
abstract class Component {
protected parent!: Component | null;
public setParent(parent: Component | null) {
this.parent = parent;
}
public getParent(): Component | null {
return this.parent;
}
public add(component: Component): void { }
public remove(component: Component): void { }
public isComposite(): boolean {
return false;
}
public abstract operation(): string;
}
// å¶å æ§è¡å
·ä½çå·¥ä½ï¼ä¸åå
å«å项ç®
class Leaf extends Component {
public operation(): string {
return 'Leaf';
}
}
// å®¹å¨ å°å
·ä½å·¥ä½å§æç»å项ç®ï¼ç¶åæ±æ»ç»æ
class Composite extends Component {
protected children: Component[] = [];
public add(component: Component): void {
this.children.push(component);
component.setParent(this);
}
public remove(component: Component): void {
const componentIndex = this.children.indexOf(component);
this.children.splice(componentIndex, 1);
component.setParent(null);
}
public isComposite(): boolean {
return true;
}
public operation(): string {
const results = [];
for (const child of this.children) {
results.push(child.operation());
}
return `Branch(${results.join('+')})`;
}
}
// 客æ·ç«¯ éè¿åºç¡æ¥å£ä¸ææçç»ä»¶é¾æ¥
function clientCode(component: Component) {
console.log(`RESULT: ${component.operation()}`);
}
const simple = new Leaf();
console.log('Client: ç®åç:');
clientCode(simple); // RESULT: Leaf
const tree = new Composite();
const branch1 = new Composite();
branch1.add(new Leaf());
branch1.add(new Leaf());
const branch2 = new Composite();
branch2.add(new Leaf());
tree.add(branch1);
tree.add(branch2);
console.log('Client: 夿ç:');
clientCode(tree); // RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
function clientCode2(component1: Component, component2: Component) {
if (component1.isComposite()) {
component1.add(component2);
}
console.log(`RESULT: ${component1.operation()}`);
}
console.log('Client: å½å¨ç®¡çæ ç¶ç»ææ¶ï¼ä¸éè¦æ£æ¥ç»ä»¶ç±»');
clientCode2(tree, simple); // RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
ç®åæ¥è¯´ï¼ç»åæ¨¡å¼æä¸»è¦çåè½æ¯å¨æ´ä¸ªæ ç¶ç»æä¸éå½è°ç¨æ¹æ³å¹¶å¯¹ç»æè¿è¡æ±æ»ã
- è£ é¥°å¨æ¨¡å¼
è£ é¥°æ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ å è®¸ä½ éè¿å°å¯¹è±¡æ¾å ¥å å«è¡ä¸ºçç¹æ®å°è£ å¯¹è±¡ä¸æ¥ä¸ºå对象ç»å®æ°çè¡ä¸ºã
举个ç°å®çä¾åï¼æ¯å¦å¤©å·å è¡£æï¼è§å¾å·äºå¯ä»¥å ä¸ä»¶æ¯è¡£ï¼è¿è§å¾å·å¯ä»¥åå ä¸ä»¶ç¾½ç»æãè¿äºè¡£ç©æ©å±äºä½ çåºæ¬è¡ä¸ºï¼ä½ä»ä»¬å¹¶ä¸æ¯ä½ çä¸é¨åï¼å¦æä¸åéè¦äºï¼å¯ä»¥éæ¶è±æã妿ä¸é¨äºï¼è¿å¯ä»¥éæ¶åå ä¸ä»¶é¨è¡£ã
è£ é¥°å¨æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
interface Component { // å®ä¹äºå¯è¢«è£
饰å¨ä¿®æ¹çæä½
operation(): string;
}
// å
·ä½é¨ä»¶æä¾äºæä½çé»è®¤å®ç° 使¯è£
饰类å¯ä»¥æ¹åè¿äºæä½
class ConcreteComponent implements Component {
public operation(): string {
return 'ConcreteComponent';
}
}
//
class Decorator implements Component {
protected component: Component;
constructor(component: Component) {
this.component = component;
}
public operation(): string {
return this.component.operation();
}
}
class ConcreteDecoratorA extends Decorator {
public operation(): string {
return `ConcreteDecoratorA(${super.operation()})`;
}
}
class ConcreteDecoratorB extends Decorator {
public operation(): string {
return `ConcreteDecoratorB(${super.operation()})`;
}
}
// 客æ·ç«¯
function clientCode(component: Component) {
console.log(`RESULT: ${component.operation()}`);
}
const simple = new ConcreteComponent();
console.log('Client: ç®åçé¨ä»¶:');
clientCode(simple); // RESULT: ConcreteComponent
const decorator1 = new ConcreteDecoratorA(simple);
const decorator2 = new ConcreteDecoratorB(decorator1);
console.log('Client: è£
饰å¨é¨ä»¶:');
clientCode(decorator2); // RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
ç®çæ¥è¯´ï¼ç®æ 对象åè£ é¥°å¨æ¯éµå¾ªå䏿¥å£çï¼å æ¤å¯ä»¥ä½¿ç¨è£ 饰对对象è¿è¡æ 鿬¡çå°è£ ï¼ç»æå¯¹è±¡å°è·å¾ææè£ 饰å¨è£ 饰åçå å ç»æã
- éé 卿¨¡å¼
éé 卿¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ å®è½ä½¿æ¥å£ä¸å ¼å®¹ç对象è½å¤ç¸äºåä½ã
举个ç°å®çä¾åï¼çµæºéé å¨ã
éé 卿¨¡å¼ç»æï¼
代ç 示ä¾ï¼
class Target { // ç®æ
public request(): string {
return 'Target: The default target\'s behavior.';
}
}
class Adaptee { // 被éé
è
public specificRequest(): string {
return '.eetpadA eht fo roivaheb laicepS';
}
}
class Adapter extends Target {
private adaptee: Adaptee;
constructor(adaptee: Adaptee) {
super();
this.adaptee = adaptee;
}
public request(): string {
const result = this.adaptee.specificRequest().split('').reverse().join('');
return `Adapter: (TRANSLATED) ${result}`;
}
}
// 客æ·ç«¯ æ¯æææéµå¾ªTargetæ¥å£çç±»
function clientCode(target: Target) {
console.log(target.request());
}
const target = new Target();
clientCode(target); // Target: è¿æ¯é»è®¤çç®æ è¡ä¸º.
const adaptee = new Adaptee();
console.log(`Adaptee: ${adaptee.specificRequest()}`); // Adaptee: .eetpadA eht fo roivaheb laicepS
const adapter = new Adapter(adaptee);
clientCode(adapter); // Adapter: (TRANSLATED) Special behavior of the Adaptee.
ç®èè¨ä¹ï¼éé 卿¥æ¶å¯¹ä¸ä¸ªå¯¹è±¡çè°ç¨ï¼å¹¶å°å ¶è½¬æ¢ä¸ºå¦ä¸ä¸ªå¯¹è±¡å¯è¯å«çæ ¼å¼åæ¥å£ã
- ä»£çæ¨¡å¼
ä»£çæ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ å®è½å¤æä¾å¯¹è±¡çæ¿ä»£åæå ä½ç¬¦ãä»£çæ§å¶ç对äºå对象ç访é®ï¼ å¹¶å 许å¨å°è¯·æ±æäº¤ç»å¯¹è±¡ååè¿è¡ä¸äºå¤çã
举个ç°å®çä¾åï¼æä»¬çæ°åæ¯ä»å·¥å ·æ¯å¦æ¯ä»å®æ¯ä»ã微信æ¯ä»å°±æ¯ç°éç代çï¼ä»ä»¬é½å®ç°äºåä¸çæ¥å£ï¼åå¯ä»¥ç¨äºæ¯ä»ãæ¶è´¹è å被æ¶è´¹è é½ä¼éå¸¸çæ»¡æï¼å ä¸ºåæ¹é½å¾ä¾¿æ·ã
ä»£çæ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
interface ServiceInterface { // 声ææå¡æ¥å£ï¼å®é
æå¡è
å代çè
è¦éµå¾ªç¸åçæ¥å£
request(): void;
}
// å®é
æå¡è
class Service implements ServiceInterface {
public request(): void {
console.log('å®é
æå¡è
: å¤ç请æ±');
}
}
// 代çè
class Proxy implements ServiceInterface {
private service: Service;
// 代çä¼ç»´æ¤ä¸ä¸ªå¯¹å®é
æå¡è
çå¼ç¨
constructor(service: Service) {
this.service = service;
}
public request(): void {
if (this.checkAccess()) {
this.service.request();
this.logAccess();
}
}
private checkAccess(): boolean {
// å¨è¿éæ§è¡ä¸äºå¤ç
console.log('代çï¼è§¦åçæ£ç请æ±ä¹åè¿è¡æ£æ¥è®¿é®');
return true;
}
private logAccess(): void {
console.log('代çï¼è¯·æ±ä¹åçä¸äºå¤ç');
}
}
// 客æ·ç«¯ä»£ç
function clientCode(serviceInterface: ServiceInterface) {
serviceInterface.request();
}
// 客æ·ç«¯ç´æ¥è°ç¨å®é
æå¡è
const service = new Service();
clientCode(service); // å®é
æå¡è
: å¤ç请æ±.
// 客æ·ç«¯éè¿ä»£çè°ç¨å®é
æå¡è
const proxy = new Proxy(service);
clientCode(proxy); // 代çï¼è§¦åçæ£ç请æ±ä¹åè¿è¡æ£æ¥è®¿é®. å®é
æå¡è
: å¤ç请æ±. 代çï¼è¯·æ±ä¹åçä¸äºå¤ç.
- äº«å æ¨¡å¼
äº«å æ¨¡å¼æ¯ä¸ç§ç»æå设计模å¼ï¼ 宿å¼äºå¨æ¯ä¸ªå¯¹è±¡ä¸ä¿åæææ°æ®çæ¹å¼ï¼ éè¿å ±äº«å¤ä¸ªå¯¹è±¡æå ±æçç¸åç¶æï¼ è®©ä½ è½å¨æéçå å容éä¸è½½å ¥æ´å¤å¯¹è±¡ã
享åå æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
// åå¨å
±æç¶æï¼æ¥æ¶å
¶ä½ç¶æ
class Flyweight {
private sharedState: any;
constructor(sharedState: any) {
this.sharedState = sharedState;
}
public operation(uniqueState): void {
const s = JSON.stringify(this.sharedState);
const u = JSON.stringify(uniqueState);
console.log(`享å
: å
±äº« (${s}),ç¬æ (${u})`);
}
}
// å建å管çFlyweight对象
class FlyweightFactory {
private flyweights: {[key: string]: Flyweight} = <any>{};
constructor(initialFlyweights: string[][]) {
for (const state of initialFlyweights) {
this.flyweights[this.getKey(state)] = new Flyweight(state);
}
}
private getKey(state: string[]): string {
return state.join('_');
}
public getFlyweight(sharedState: string[]): Flyweight {
const key = this.getKey(sharedState);
if (!(key in this.flyweights)) {
console.log('享å
å·¥å: ä¸è½å¤å¯»æ¾å°äº«å
ï¼å建ä¸ä¸ªæ°ç');
this.flyweights[key] = new Flyweight(sharedState);
} else {
console.log('享å
å·¥å: æ¾å°äºå·²åå¨ç享å
');
}
return this.flyweights[key];
}
public listFlyweights(): void {
const count = Object.keys(this.flyweights).length;
console.log(`享å
å·¥å: ææ ${count} 个享å
:`);
for (const key in this.flyweights) {
console.log(key);
}
}
}
// 客æ·ç«¯ä»£ç å
å建ä¸äºé¢å
å¡«å
çflyweight
const factory = new FlyweightFactory([
['Chevrolet', 'Camaro2018', 'pink'],
['Mercedes Benz', 'C300', 'black'],
['Mercedes Benz', 'C500', 'red'],
['BMW', 'M5', 'red'],
['BMW', 'X6', 'white'],
]);
factory.listFlyweights(); // 享å
å·¥å: ææ5个享å
:
// Chevrolet-Camaro2018-pink
// Mercedes Benz-C300-black
// Mercedes Benz-C500-red
// BMW-M5-red
// BMW-X6-white
function addCarToPoliceDatabase(
ff: FlyweightFactory, plates: string, owner: string,
brand: string, model: string, color: string,
) {
const flyweight = ff.getFlyweight([brand, model, color]);
flyweight.operation([plates, owner]);
}
addCarToPoliceDatabase(factory, 'CL234IR', 'James Doe', 'BMW', 'M5', 'red');
// 享å
å·¥å: æ¾å°äºå·²åå¨ç享å
.
// 享å
: å
±äº« (['BMW', 'M5', 'red']), ç¬æ (['CL234IR', 'James Doe']).
addCarToPoliceDatabase(factory, 'CL234IR', 'James Doe', 'BMW', 'X1', 'red');
// 享å
å·¥å: ä¸è½å¤å¯»æ¾å°äº«å
ï¼å建ä¸ä¸ªæ°ç
// 享å
: å
±äº« (['BMW', 'X1', 'red']), ç¬æ (['CL234IR', 'James Doe']) state.
factory.listFlyweights(); // 享å
å·¥å: ææ6个享å
:
// Chevrolet-Camaro2018-pink
// Mercedes Benz-C300-black
// Mercedes Benz-C500-red
// BMW-M5-red
// BMW-X6-white
// BMW-X1-red
ç®åæ¥è¯´ï¼äº«å 模å¼éè¿å ±äº«å¤ä¸ªå¯¹è±¡çé¨åç¶ææ¥å®ç°ä¸è¿°åè½ï¼äº«å ä¼å°ä¸å对象çç¸åæ°æ®è¿è¡ç¼å以èçå åãå¦åä¸è¿°ä¾åä¸ï¼è½¦çåå·ä¼è¢«åå¨å¨äº«å ä¸ï¼è½¦ç主人æ¯ç¬äº«çãå½å°ä¸ä¸ª 主人-è½¦è¾ æ°æ®å å ¥æ°æ®åºä¸æ¶ï¼äº«å å·¥åå æ¥æ¾äº«å 䏿¯å¦å·²åå¨è¯¥åå·è½¦çæ°æ®ï¼æçè¯ç´æ¥è¿åï¼æ²¡æçè¯å建è¿ä¸ªåå·ã
âè¡ä¸ºå
è¡ä¸ºæ¨¡å¼è´è´£å¯¹è±¡é´ç髿æ²éåèè´£å§æ´¾ã
- è¿ä»£å¨æ¨¡å¼
è¿ä»£å¨æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å®è½å¤å¨ä¸æ´é²éååºå±è¡¨ç°å½¢å¼ ï¼åè¡¨ã æ åæ çï¼ çæ åµä¸éåéå䏿æçå ç´ ã
举个ç°å®çä¾åï¼åå¦å»åäº¬æ æ¸¸ï¼æ 宫ãé¿åã天å®é¨ãé¢ååãåå¤§ãæ¸ åæ¯æ¤æ¬¡æ è¡ç游è§ç®æ ï¼å¯ä»¥å°ä»ä»¬ç»æä¸ä¸ªç®çå°éåã第ä¸ç§æ¸¸è§æ¹å¼æ¯æç §èªå·±çææ¿é¡ºåºå»æ¸¸ç©ï¼ç¬¬äºç§æ¹å¼æ¯æç §æäºå主æ¨èçæ¸¸è§é¡ºåºæ¸¸ç©ï¼ç¬¬ä¸ç§æ¹å¼æ¯æ¥ä¸ªæ è¡å¢ï¼æç §æ è¡å¢å®æçé¡ºåºæ¸¸ç©ã以ä¸è¿ä¸ç§éæ©å°±æ¯ç®çå°éåçè¿ä»£å¨ã
è¿ä»£å¨æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
interface Iterator<T> {
current(): T; // è¿åå½åçå
ç´
next(): T; // è¿åä¸ä¸ä¸ªå
ç´
key(): number; // è¿åå½åå
ç´ çkey
valid(): boolean; // æ£æµå½åä½ç½®æ¯å¦æ¯ææç
rewind(): void; // å°è¿ä»£å¨åéå°ç¬¬ä¸ä¸ªå
ç´
}
interface Aggregator {
getIterator(): Iterator<string>; // è·åå¤é¨è¿ä»£å¨
}
// å
·ä½è¿ä»£å¨å®ç°åç§éåç®æ³ãè¿äºç±»å¨ä»»ä½æ¶åé½åå¨å½åéåä½ç½®
class AlphabeticalOrderIterator implements Iterator<string> {
private collection: WordsCollection;
private position: number = 0;
private reverse: boolean = false;
constructor(collection: WordsCollection, reverse: boolean = false) {
this.collection = collection;
this.reverse = reverse;
if (reverse) {
this.position = collection.getCount() - 1;
}
}
public rewind() {
this.position = this.reverse ?
this.collection.getCount() - 1 :
0;
}
public current(): string {
return this.collection.getItems()[this.position];
}
public key(): number {
return this.position;
}
public next(): string {
const item = this.collection.getItems()[this.position];
this.position += this.reverse ? -1 : 1;
return item;
}
public valid(): boolean {
if (this.reverse) {
return this.position >= 0;
}
return this.position < this.collection.getCount();
}
}
// å
·ä½éåæä¾ä¸ä¸ªæå¤ä¸ªæ¹æ³æ¥æ£ç´¢æ°çè¿ä»£å¨å®ä¾ï¼ä¸éåç±»å
¼å®¹ã
class WordsCollection implements Aggregator {
private items: string[] = [];
public getItems(): string[] {
return this.items;
}
public getCount(): number {
return this.items.length;
}
public addItem(item: string): void {
this.items.push(item);
}
public getIterator(): Iterator<string> {
return new AlphabeticalOrderIterator(this);
}
public getReverseIterator(): Iterator<string> {
return new AlphabeticalOrderIterator(this, true);
}
}
// 客æ·ç«¯ä»£ç
const collection = new WordsCollection();
collection.addItem('First');
collection.addItem('Second');
collection.addItem('Third');
const iterator = collection.getIterator();
console.log('Straight traversal:');
while (iterator.valid()) {
console.log(iterator.next()); // First Second Third
}
const reverseIterator = collection.getReverseIterator();
while (reverseIterator.valid()) {
console.log(reverseIterator.next()); // Third Second First
}
æç®åççè§£æ¹å¼çè¯ï¼å ¶å®å°±æ¯æä»¬å¸¸è¯´çES6ä¸çè¿ä»£å¨ã
- è§£é卿¨¡å¼
è§£é卿¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ãç»å®ä¸ä¸ªè¯è¨, å®ä¹å®çææ³çä¸ç§è¡¨ç¤ºï¼å¹¶å®ä¹ä¸ä¸ªè§£éå¨, 该解éå¨ä½¿ç¨è¯¥è¡¨ç¤ºæ¥è§£éè¯è¨ä¸çå¥åã
代ç 示ä¾ï¼
class Context {
constructor() {
this._list = []; // åæ¾ ç»ç»ç¬¦è¡¨è¾¾å¼
this._sum = 0; // åæ¾ éç»ç»ç¬¦è¡¨è¾¾å¼(è¿ç®ç»æ)
}
get sum() {
return this._sum;
}
set sum(newValue) {
this._sum = newValue;
}
add(expression) {
this._list.push(expression);
}
get list() {
return [...this._list];
}
}
class PlusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error("TypeError");
}
context.sum = ++context.sum;
}
}
class MinusExpression {
interpret(context) {
if (!(context instanceof Context)) {
throw new Error("TypeError");
}
context.sum = --context.sum;
}
}
// 客æ·ç«¯ä»£ç
const context = new Context();
// æ·»å å æ³è¡¨è¾¾å¼
context.add(new PlusExpression());
// æ·»å å æ³è¡¨è¾¾å¼
context.add(new PlusExpression());
// æ·»å åæ³è¡¨è¾¾å¼
context.add(new MinusExpression());
// 便¬¡æ§è¡: å æ³ãå æ³ãåæ³è¡¨è¾¾å¼
context.list.forEach(expression => expression.interpret(context));
console.log(context.sum); // 1
- è§å¯è 模å¼
è§å¯è æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼å被称为åå¸è®¢é 模å¼ãå®å 许å®ä¹ä¸ç§è®¢é æºå¶ï¼ å¯å¨å¯¹è±¡äºä»¶åçæ¶éç¥å¤ä¸ª âè§å¯â 该对象çå ¶ä»å¯¹è±¡ã
举个ç°å®çä¾åï¼æ¯å¦ä½ 订é äºäººæ°æ¥æ¥ï¼æ¯å½å®åççæ¶åï¼é½ä¼æé®éåå°æ¥çº¸éå°ä½ æä¸ï¼èä¸éè¦ä½ è·å»æ¥åäºèªå·±è´ä¹°ãåºç社为åå¸è ï¼ä½ 为订é è ï¼åºç社维æ¤çä¸ä»½è®¢é è çååï¼å½ä½ 䏿³åè®¢é æ¶å¯ä»¥ç³è¯·éåºè®¢é ã
è§å¯è 模å¼ç»æï¼
代ç 示ä¾ï¼
interface Subject { // 声æäºä¸ç»ç®¡ç订é
è
çæ¹æ³
attach(observer: Observer): void; // 为订é
è
éå è§å¯è
detach(observer: Observer): void; // ä»è®¢é
è
身ä¸å¥ç¦»è§å¯è
notify(): void; // éç¥ææè§å¯è
çæ¹æ³
}
// å
·ä½è®¢é
è
class ConcreteSubject implements Subject {
public state: number;
private observers: Observer[] = [];
public attach(observer: Observer): void {
const isExist = this.observers.includes(observer);
if (isExist) {
return console.log('Subject: Observer has been attached already.');
}
console.log('Subject: Attached an observer.');
this.observers.push(observer);
}
public detach(observer: Observer): void {
const observerIndex = this.observers.indexOf(observer);
if (observerIndex === -1) {
return console.log('Subject: Nonexistent observer.');
}
this.observers.splice(observerIndex, 1);
console.log('Subject: Detached an observer.');
}
// è§¦åæ¯ä¸ªè®¢é
è
æ´æ°
public notify(): void {
console.log('Subject: Notifying observers...');
for (const observer of this.observers) {
observer.update(this);
}
}
// ä¸å¡é»è¾çï¼å½å
¶åçååæ¶ï¼è§¦ånotifyæ¹æ³
public someBusinessLogic(): void {
console.log('\nSubject: I\'m doing something important.');
this.state = Math.floor(Math.random() * (10 + 1));
console.log(`Subject: My state has just changed to: ${this.state}`);
this.notify();
}
}
interface Observer { // å£°ææ´æ°æ¹æ³ï¼ç±è®¢é
è
è°ç¨
// Receive update from subject.
update(subject: Subject): void;
}
// å
·ä½è§å¯è
class ConcreteObserverA implements Observer {
public update(subject: Subject): void {
if (subject instanceof ConcreteSubject && subject.state < 3) {
console.log('ConcreteObserverA: Reacted to the event.');
}
}
}
class ConcreteObserverB implements Observer {
public update(subject: Subject): void {
if (subject instanceof ConcreteSubject && (subject.state === 0 || subject.state >= 2)) {
console.log('ConcreteObserverB: Reacted to the event.');
}
}
}
// 客æ·ç«¯ä»£ç
const subject = new ConcreteSubject();
const observer1 = new ConcreteObserverA();
subject.attach(observer1); // Subject: Attached an observer.
const observer2 = new ConcreteObserverB();
subject.attach(observer2); // Subject: Attached an observer.
subject.someBusinessLogic(); // Subject: I'm doing something important. Subject: My state has just changed to: 6. Subject: Notifying observers... ConcreteObserverB: Reacted to the event.
subject.someBusinessLogic(); // Subject: I'm doing something important. Subject: My state has just changed to: 1. Subject: Notifying observers... ConcreteObserverA: Reacted to the event.
subject.detach(observer2); // Subject: Detached an observer.
subject.someBusinessLogic(); // Subject: I'm doing something important. Subject: My state has just changed to: 5. Subject: Notifying observers...
- ä¸ä»è 模å¼
ä¸ä»è æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ è½å¤åå°å¯¹è±¡ä¹é´æ··ä¹±æ åºçä¾èµå ³ç³»ã该模å¼ä¼éå¶å¯¹è±¡ä¹é´çç´æ¥äº¤äºï¼ 迫使å®ä»¬éè¿ä¸ä¸ªä¸ä»è 对象è¿è¡åä½ã
举个ç°å®çä¾åï¼èªçä¸èªçä¹é´ä¸ä¼ç´æ¥æ²éï¼èæ¯ä¸å¡å°æ²éï¼ä»è坿¥é¿å èªçº¿äº¤åãéå¤èå¯è½å¼èµ·ç飿ºä¹é´ç碰æãå½ç¶ç°å®ä¸è¿æå¾å¤å ¶ä»çä¾åï¼ä¸ä»è 模å¼å ¶å®å°±æ¯æä»¬åé¢ä¸çè§£çä¸ä»è çææã
ä¸ä»è 模å¼ç»æï¼
代ç 示ä¾ï¼
interface Mediator {
notify(sender: object, event: string): void;
}
class ConcreteMediator implements Mediator {
private component1: Component1;
private component2: Component2;
constructor(c1: Component1, c2: Component2) {
this.component1 = c1;
this.component1.setMediator(this);
this.component2 = c2;
this.component2.setMediator(this);
}
public notify(sender: object, event: string): void {
if (event === 'A') {
console.log('Mediator reacts on A and triggers following operations:');
this.component2.doC();
}
if (event === 'D') {
console.log('Mediator reacts on D and triggers following operations:');
this.component1.doB();
this.component2.doC();
}
}
}
class BaseComponent {
protected mediator: Mediator;
constructor(mediator?: Mediator) {
this.mediator = mediator!;
}
public setMediator(mediator: Mediator): void {
this.mediator = mediator;
}
}
class Component1 extends BaseComponent {
public doA(): void {
console.log('Component 1 does A.');
this.mediator.notify(this, 'A');
}
public doB(): void {
console.log('Component 1 does B.');
this.mediator.notify(this, 'B');
}
}
class Component2 extends BaseComponent {
public doC(): void {
console.log('Component 2 does C.');
this.mediator.notify(this, 'C');
}
public doD(): void {
console.log('Component 2 does D.');
this.mediator.notify(this, 'D');
}
}
// 客æ·ç«¯ä»£ç
const c1 = new Component1();
const c2 = new Component2();
const mediator = new ConcreteMediator(c1, c2);
// 触åæä½A
c1.doA(); // Component 1 does A. Mediator reacts on A and triggers following operations: Component 2 does C.
// 触åæä½B
c2.doD(); // Component 2 does D. Mediator reacts on D and triggers following operations: Component 1 does B. Component 2 does C.
ç¨åºç»ä»¶éè¿ç¹æ®çä¸ä»è 对象è¿è¡é´æ¥æ²éï¼ è¾¾å°äºåå°ç»ä»¶ä¹é´ä¾èµå ³ç³»çç®çã
- 访é®è 模å¼
访é®è æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å®è½å°ç®æ³ä¸å ¶æä½ç¨ç对象éç¦»å¼æ¥ã
举个ç°å®çä¾åï¼ä¸ä¸ªæ¿å°äº§éå®äººåï¼ä»å¯ä»¥ååç§åæ ·ç人æ¨éï¼å¦æé¢å¯¹å¯è±ªï¼ä»æ¨éå«å¢ ï¼å¦æé¢å¯¹é«æ¶å ¥äººç¾¤ï¼ä»æ¨éæ®å¤§å¹³å±ï¼å¦æé¢å¯¹æ®éæ¶å ¥äººç¾¤ï¼ä»æ¨éæ®éé«å±ã
访é®è 模å¼ç»æï¼
代ç 示ä¾ï¼
interface Component {
accept(visitor: Visitor): void;
}
class ConcreteComponentA implements Component {
public accept(visitor: Visitor): void {
visitor.visitConcreteComponentA(this);
}
public exclusiveMethodOfConcreteComponentA(): string {
return 'A';
}
}
class ConcreteComponentB implements Component {
public accept(visitor: Visitor): void {
visitor.visitConcreteComponentB(this);
}
public specialMethodOfConcreteComponentB(): string {
return 'B';
}
}
interface Visitor {
visitConcreteComponentA(element: ConcreteComponentA): void;
visitConcreteComponentB(element: ConcreteComponentB): void;
}
class ConcreteVisitor1 implements Visitor {
public visitConcreteComponentA(element: ConcreteComponentA): void {
console.log(`${element.exclusiveMethodOfConcreteComponentA()} + ConcreteVisitor1`);
}
public visitConcreteComponentB(element: ConcreteComponentB): void {
console.log(`${element.specialMethodOfConcreteComponentB()} + ConcreteVisitor1`);
}
}
class ConcreteVisitor2 implements Visitor {
public visitConcreteComponentA(element: ConcreteComponentA): void {
console.log(`${element.exclusiveMethodOfConcreteComponentA()} + ConcreteVisitor2`);
}
public visitConcreteComponentB(element: ConcreteComponentB): void {
console.log(`${element.specialMethodOfConcreteComponentB()} + ConcreteVisitor2`);
}
}
// 客æ·ç«¯ä»£ç
function clientCode(components: Component[], visitor: Visitor) {
// ...
for (const component of components) {
component.accept(visitor);
}
// ...
}
const components = [
new ConcreteComponentA(),
new ConcreteComponentB(),
];
// éè¿åºç¡è®¿é®è
æ¥å£ï¼å®¢æ·ç«¯ä»£ç 䏿æç访é®è
ä¸åå·¥ä½
const visitor1 = new ConcreteVisitor1();
clientCode(components, visitor1); // A + ConcreteVisitor1 B + ConcreteVisitor1
// åæ ·ç客æ·ç«¯ä»£ç å¯ä»¥ä¸ä¸åç±»åç访é®è
ä¸åå·¥ä½
const visitor2 = new ConcreteVisitor2();
clientCode(components, visitor2); // A + ConcreteVisitor2 B + ConcreteVisitor2
- ç¶ææ¨¡å¼
ç¶ææ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å¯ä»¥å¨ä¸ä¸ªå¯¹è±¡çå é¨ç¶æååæ¶æ¹åå ¶è¡ä¸ºï¼ ä½¿å ¶çä¸å»å°±åæ¹åäºèªèº«æå±çç±»ä¸æ ·ã
举个å®é çä¾åï¼ä½ çææºï¼æè¯è´¹ç¶æï¼å¯ä»¥æçµè¯ï¼æ è¯è´¹ç¶æï¼ä¸å¯ä»¥æçµè¯ã设计ä¸å°±æ¯ä¸åçç¶æä¸æå¯¹åºçåè½ä¸åã
ç¶ææ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
class Context {
private state: State;
constructor(state: State) {
this.transitionTo(state);
}
public transitionTo(state: State): void {
console.log(`Context: Transition to ${(<any>state).constructor.name}.`);
this.state = state;
this.state.setContext(this);
}
public request1(): void {
this.state.handle1();
}
public request2(): void {
this.state.handle2();
}
}
abstract class State {
protected context: Context;
public setContext(context: Context) {
this.context = context;
}
public abstract handle1(): void;
public abstract handle2(): void;
}
class ConcreteStateA extends State {
public handle1(): void {
console.log('ConcreteStateA handles request1.');
console.log('ConcreteStateA wants to change the state of the context.');
this.context.transitionTo(new ConcreteStateB());
}
public handle2(): void {
console.log('ConcreteStateA handles request2.');
}
}
class ConcreteStateB extends State {
public handle1(): void {
console.log('ConcreteStateB handles request1.');
}
public handle2(): void {
console.log('ConcreteStateB handles request2.');
console.log('ConcreteStateB wants to change the state of the context.');
this.context.transitionTo(new ConcreteStateA());
}
}
// 客æ·ç«¯ä»£ç
const context = new Context(new ConcreteStateA());
context.request1(); // Context: Transition to ConcreteStateA. ConcreteStateA handles request1. ConcreteStateA wants to change the state of the context.
context.request2(); // Context: Transition to ConcreteStateB. ConcreteStateB handles request2. ConcreteStateB wants to change the state of the context. Context: Transition to ConcreteStateA.
- å¤å¿å½æ¨¡å¼
å¤å¿å½æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å 许å¨ä¸æ´é²å¯¹è±¡å®ç°ç»èçæ åµä¸ä¿å忢å¤å¯¹è±¡ä¹åçç¶æï¼å 许çæå¯¹è±¡ç¶æçå¿«ç §å¹¶å¨ä»¥åå°å ¶è¿åï¼å®ä¸ä¼å½±å宿å¤çç对象çå é¨ç»æï¼ ä¹ä¸ä¼å½±åå¿«ç §ä¸ä¿åçæ°æ®ã
å¤å¿å½æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
class Originator {
private state: string;
constructor(state: string) {
this.state = state;
console.log(`Originator: My initial state is: ${state}`);
}
public doSomething(): void {
console.log('Originator: I\'m doing something important.');
this.state = this.generateRandomString(30);
console.log(`Originator: and my state has changed to: ${this.state}`);
}
private generateRandomString(length: number = 10): string {
const charSet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
return Array
.apply(null, { length })
.map(() => charSet.charAt(Math.floor(Math.random() * charSet.length)))
.join('');
}
public save(): Memento {
return new ConcreteMemento(this.state);
}
public restore(memento: Memento): void {
this.state = memento.getState();
console.log(`Originator: My state has changed to: ${this.state}`);
}
}
interface Memento {
getState(): string;
getName(): string;
getDate(): string;
}
class ConcreteMemento implements Memento {
private state: string;
private date: string;
constructor(state: string) {
this.state = state;
this.date = new Date().toISOString().slice(0, 19).replace('T', ' ');
}
public getState(): string {
return this.state;
}
public getName(): string {
return `${this.date} / (${this.state.substr(0, 9)}...)`;
}
public getDate(): string {
return this.date;
}
}
class Caretaker {
private mementos: Memento[] = [];
private originator: Originator;
constructor(originator: Originator) {
this.originator = originator;
}
public backup(): void {
console.log('\nCaretaker: Saving Originator\'s state...');
this.mementos.push(this.originator.save());
}
public undo(): void {
if (!this.mementos.length) {
return;
}
const memento = this.mementos.pop();
console.log(`Caretaker: Restoring state to: ${memento.getName()}`);
this.originator.restore(memento);
}
public showHistory(): void {
console.log('Caretaker: Here\'s the list of mementos:');
for (const memento of this.mementos) {
console.log(memento.getName());
}
}
}
// 客æ·ç«¯ä»£ç
const originator = new Originator('Super-duper-super-puper-super.');
const caretaker = new Caretaker(originator);
caretaker.backup();
originator.doSomething();
caretaker.backup();
originator.doSomething();
caretaker.backup();
originator.doSomething();
console.log('');
caretaker.showHistory();
console.log('\nClient: Now, let\'s rollback!\n');
caretaker.undo();
console.log('\nClient: Once more!\n');
caretaker.undo();
Originator: My initial state is: Super-duper-super-puper-super.
Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: qXqxgTcLSCeLYdcgElOghOFhPGfMxo
Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: iaVCJVryJwWwbipieensfodeMSWvUY
Caretaker: Saving Originator's state...
Originator: I'm doing something important.
Originator: and my state has changed to: oSUxsOCiZEnohBMQEjwnPWJLGnwGmy
Caretaker: Here's the list of mementos:
2019-02-17 15:14:05 / (Super-dup...)
2019-02-17 15:14:05 / (qXqxgTcLS...)
2019-02-17 15:14:05 / (iaVCJVryJ...)
Client: Now, let's rollback!
Caretaker: Restoring state to: 2019-02-17 15:14:05 / (iaVCJVryJ...)
Originator: My state has changed to: iaVCJVryJwWwbipieensfodeMSWvUY
Client: Once more!
Caretaker: Restoring state to: 2019-02-17 15:14:05 / (qXqxgTcLS...)
Originator: My state has changed to: qXqxgTcLSCeLYdcgElOghOFhPGfMxo
- çç¥æ¨¡å¼
çç¥æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ è½è®©å®ä¹ä¸ç³»åç®æ³ï¼ å¹¶å°æ¯ç§ç®æ³å嫿¾å ¥ç¬ç«çç±»ä¸ï¼ ä»¥ä½¿ç®æ³ç对象è½å¤ç¸äºæ¿æ¢ã
举个ç°å®çä¾åï¼æ¯å¦èµ¶ç«è½¦ï¼å°è¾¾ç«è½¦ç«ççç¥æå ¬äº¤è½¦ãå°éãåºç§è½¦çï¼æä»¬å¯ä»¥æ ¹æ®é¢ç®ææ¶é´çå ç´ éæ©å ¶ä¸çä¸ç§çç¥ã
çç¥æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
class Context {
private strategy: Strategy;
constructor(strategy: Strategy) {
this.strategy = strategy;
}
public setStrategy(strategy: Strategy) {
this.strategy = strategy;
}
public doSomeBusinessLogic(): void {
console.log('Context: Sorting data using the strategy (not sure how it\'ll do it)');
const result = this.strategy.doAlgorithm(['a', 'b', 'c', 'd', 'e']);
console.log(result.join(','));
}
}
interface Strategy {
doAlgorithm(data: string[]): string[];
}
class ConcreteStrategyA implements Strategy {
public doAlgorithm(data: string[]): string[] {
return data.sort();
}
}
class ConcreteStrategyB implements Strategy {
public doAlgorithm(data: string[]): string[] {
return data.reverse();
}
}
// 客æ·ç«¯ä»£ç
const context = new Context(new ConcreteStrategyA());
console.log('Client: Strategy is set to normal sorting.');
context.doSomeBusinessLogic();
console.log('');
console.log('Client: Strategy is set to reverse sorting.');
context.setStrategy(new ConcreteStrategyB());
context.doSomeBusinessLogic();
Client: Strategy is set to normal sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
a,b,c,d,e
Client: Strategy is set to reverse sorting.
Context: Sorting data using the strategy (not sure how it'll do it)
e,d,c,b,a
- æ¨¡æ¿æ¹æ³æ¨¡å¼
æ¨¡æ¿æ¹æ³æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å®å¨åºç±»ä¸å®ä¹äºä¸ä¸ªç®æ³çæ¡æ¶ï¼ å 许åç±»å¨ä¸ä¿®æ¹ç»æçæ åµä¸éåç®æ³çç¹å®æ¥éª¤ã
举个ç°å®çä¾åï¼åæèªå»ºæ¿æä¸å¥åºå®çæ¨¡çæ¹æ³ï¼æ¯å¦ä¸ºï¼æå°åº -> 建é ä¸»ä½ -> å°é¡¶ -> éºè®¾æ°´çµ -> è£ ä¿®ï¼ï¼ä½è¿å ¶ä¸å¯æä¾å 个æ©å±ç¹ï¼ å 许æ½å¨çæ¿å±ä¸ä¸»è°æ´æåæ¿å±çé¨åç»èï¼å¦è£ ä¿®é£æ ¼ï¼è¿ä½¿å¾æåæ¿å±ä¼æä¸åã
æ¨¡çæ¹æ³æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
abstract class AbstractClass {
public templateMethod(): void {
this.baseOperation1();
this.requiredOperations1();
this.baseOperation2();
this.hook1();
this.requiredOperation2();
this.baseOperation3();
this.hook2();
}
protected baseOperation1(): void {
console.log('AbstractClass says: I am doing the bulk of the work');
}
protected baseOperation2(): void {
console.log('AbstractClass says: But I let subclasses override some operations');
}
protected baseOperation3(): void {
console.log('AbstractClass says: But I am doing the bulk of the work anyway');
}
protected abstract requiredOperations1(): void;
protected abstract requiredOperation2(): void;
protected hook1(): void { }
protected hook2(): void { }
}
class ConcreteClass1 extends AbstractClass {
protected requiredOperations1(): void {
console.log('ConcreteClass1 says: Implemented Operation1');
}
protected requiredOperation2(): void {
console.log('ConcreteClass1 says: Implemented Operation2');
}
}
class ConcreteClass2 extends AbstractClass {
protected requiredOperations1(): void {
console.log('ConcreteClass2 says: Implemented Operation1');
}
protected requiredOperation2(): void {
console.log('ConcreteClass2 says: Implemented Operation2');
}
protected hook1(): void {
console.log('ConcreteClass2 says: Overridden Hook1');
}
}
// 客æ·ç«¯ä»£ç
function clientCode(abstractClass: AbstractClass) {
// ...
abstractClass.templateMethod();
// ...
}
console.log('Same client code can work with different subclasses:');
clientCode(new ConcreteClass1());
console.log('');
console.log('Same client code can work with different subclasses:');
clientCode(new ConcreteClass2());
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
- èè´£é¾æ¨¡å¼
èè´£é¾æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å 许å°è¯·æ±æ²¿çå¤çè é¾è¿è¡åéãæ¶å°è¯·æ±åï¼ æ¯ä¸ªå¤çè åå¯å¯¹è¯·æ±è¿è¡å¤çï¼ æå°å ¶ä¼ éç»é¾ä¸çä¸ä¸ªå¤çè ã
èè´£é¾æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
interface Handler {
setNext(handler: Handler): Handler;
handle(request: string): string;
}
abstract class AbstractHandler implements Handler
{
private nextHandler: Handler;
public setNext(handler: Handler): Handler {
this.nextHandler = handler;
return handler;
}
public handle(request: string): string {
if (this.nextHandler) {
return this.nextHandler.handle(request);
}
return null;
}
}
class MonkeyHandler extends AbstractHandler {
public handle(request: string): string {
if (request === 'Banana') {
return `Monkey: I'll eat the ${request}.`;
}
return super.handle(request);
}
}
class SquirrelHandler extends AbstractHandler {
public handle(request: string): string {
if (request === 'Nut') {
return `Squirrel: I'll eat the ${request}.`;
}
return super.handle(request);
}
}
class DogHandler extends AbstractHandler {
public handle(request: string): string {
if (request === 'MeatBall') {
return `Dog: I'll eat the ${request}.`;
}
return super.handle(request);
}
}
function clientCode(handler: Handler) {
const foods = ['Nut', 'Banana', 'Cup of coffee'];
for (const food of foods) {
console.log(`Client: Who wants a ${food}?`);
const result = handler.handle(food);
if (result) {
console.log(` ${result}`);
} else {
console.log(` ${food} was left untouched.`);
}
}
}
// 客æ·ç«¯ä»£ç
const monkey = new MonkeyHandler();
const squirrel = new SquirrelHandler();
const dog = new DogHandler();
monkey.setNext(squirrel).setNext(dog);
console.log('Chain: Monkey > Squirrel > Dog\n');
clientCode(monkey);
console.log('');
console.log('Subchain: Squirrel > Dog\n');
clientCode(squirrel);
Chain: Monkey > Squirrel > Dog
Client: Who wants a Nut?
Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
Cup of coffee was left untouched.
Subchain: Squirrel > Dog
Client: Who wants a Nut?
Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
Banana was left untouched.
Client: Who wants a Cup of coffee?
Cup of coffee was left untouched.
- å½ä»¤æ¨¡å¼
å½ä»¤æ¨¡å¼æ¯ä¸ç§è¡ä¸ºè®¾è®¡æ¨¡å¼ï¼ å®å¯å°è¯·æ±è½¬æ¢ä¸ºä¸ä¸ªå å«ä¸è¯·æ±ç¸å ³çææä¿¡æ¯çç¬ç«å¯¹è±¡ã该转æ¢è½æ ¹æ®ä¸åç请æ±å°æ¹æ³åæ°åã å»¶è¿è¯·æ±æ§è¡æå°å ¶æ¾å ¥éåä¸ï¼ ä¸è½å®ç°å¯æ¤éæä½ã
å½ä»¤æ¨¡å¼ç»æï¼
代ç 示ä¾ï¼
interface Command {
execute(): void;
}
class SimpleCommand implements Command {
private payload: string;
constructor(payload: string) {
this.payload = payload;
}
public execute(): void {
console.log(`SimpleCommand: See, I can do simple things like printing (${this.payload})`);
}
}
class ComplexCommand implements Command {
private receiver: Receiver;
private a: string;
private b: string;
constructor(receiver: Receiver, a: string, b: string) {
this.receiver = receiver;
this.a = a;
this.b = b;
}
public execute(): void {
console.log('ComplexCommand: Complex stuff should be done by a receiver object.');
this.receiver.doSomething(this.a);
this.receiver.doSomethingElse(this.b);
}
}
class Receiver {
public doSomething(a: string): void {
console.log(`Receiver: Working on (${a}.)`);
}
public doSomethingElse(b: string): void {
console.log(`Receiver: Also working on (${b}.)`);
}
}
class Invoker {
private onStart: Command;
private onFinish: Command;
public setOnStart(command: Command): void {
this.onStart = command;
}
public setOnFinish(command: Command): void {
this.onFinish = command;
}
public doSomethingImportant(): void {
console.log('Invoker: Does anybody want something done before I begin?');
if (this.isCommand(this.onStart)) {
this.onStart.execute();
}
console.log('Invoker: ...doing something really important...');
console.log('Invoker: Does anybody want something done after I finish?');
if (this.isCommand(this.onFinish)) {
this.onFinish.execute();
}
}
private isCommand(object): object is Command {
return object.execute !== undefined;
}
}
// 客æ·ç«¯ä»£ç
const invoker = new Invoker();
invoker.setOnStart(new SimpleCommand('Say Hi!'));
const receiver = new Receiver();
invoker.setOnFinish(new ComplexCommand(receiver, 'Send email', 'Save report'));
invoker.doSomethingImportant();
Invoker: Does anybody want something done before I begin?
SimpleCommand: See, I can do simple things like printing (Say Hi!)
Invoker: ...doing something really important...
Invoker: Does anybody want something done after I finish?
ComplexCommand: Complex stuff should be done by a receiver object.
Receiver: Working on (Send email.)
Receiver: Also working on (Save report.)
åèæç®
Alexander Shvets, Dive-into Design Patterns[M], Finelybook, 2019.
å¢éä»ç»
æä»¬æ¯å¤§æ·å®ææ¯-è¥éä¸å¹³å°çç¥ææ¯-è¥é产åå¢éï¼ä¸»è¦è´è´£æ·å®å¥½ä»·ãç¾äº¿è¡¥è´´ãèåç®ã天天ç¹åç大æ·å®æ ¸å¿äº§ååå类大åçè¥éä¼åºæ´»å¨ï¼åæ¶æä»¬ä¹æ¯å端æºè½åçå ééï¼ææ¹èãåå¸ãimgcookãæºè½UIçå¤ç§ææ¯äº§åã