更多精彩内容,欢迎观看:
前端工程中的设计模式应用(中):https://developer.aliyun.com/article/1396343
- 备忘录模式
备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态,允许生成对象状态的快照并在以后将其还原,它不会影响它所处理的对象的内部结构, 也不会影响快照中保存的数据。
备忘录模式结构:
代码示例:
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等多种技术产品。