局域网站建设模版,企业vi设计公司标准版,海南企业建站,对网站界面设计起决定性作用的是本文旨在系统性介绍一下23种设计模式#xff0c;给出通俗易懂的案例、结构图及代码示例#xff0c;这也是我自身学习理解的过程。或许其中的几种设计模式写的并不是很清晰明了易懂#xff0c;更详细的可根据提到的参考文献进行深入学习。 什么是设计模式 设计模式这个概念是… 本文旨在系统性介绍一下23种设计模式给出通俗易懂的案例、结构图及代码示例这也是我自身学习理解的过程。或许其中的几种设计模式写的并不是很清晰明了易懂更详细的可根据提到的参考文献进行深入学习。 什么是设计模式 设计模式这个概念是由一本名为《设计模式可复用面向对象软件的基础》的书推广而来这本书在1994年由四个C工程师编写的。这本书探讨了面向对象的编程的能力和陷阱并介绍了23种可以用来解决编程问题的模式。这些模式并不是算法或者具体的实现它们更像是想法、观点和抽象辅助我们去解决一些特定问题。但是这些模式建立在C的OOP的基础之上当使用更现代的编程语言如JavaScript时模式可能不等效甚至给代码添加了不必要的限制但是我们仍然可以把这些模式当做一些编程知识来学习了解。我们学习使用这些模式的目的是实现代码的高内聚和低耦合提高代码的复用性让代码更容易的被他人理解并保证代码的可靠性。 23种设计模式简介 ▐ 创建型Creational5种 提供创建对象的机制 增加已有代码的灵活性和可复用性。 单例模式Singleton 保证一个类只有一个实例 并提供一个访问该实例的全局节点。 原型模式Prototype 允许把一个对象作为蓝图创建另一个对象新对象继承原对象的属性和方法。 生成器模式Builder 分“步骤”创建对象。 工厂方法模式Factory Method 提供创建对象的接口对象被创建后可以修改。 抽象工厂模式Abstract Factory 允许在不指定具体类的情况下生成一系列相关的对象。 ▐ 结构型Structural7种 介绍如何将对象和类组装成较大的结构 并同时保持结构的灵活和高效。 桥接模式Bridge 将抽象部分与它的实现部分分离使它们都可以独立地变化。 外观模式Facade 给库、框架以及其他复杂的类集提供简化的接口。 组合模式Composite 将对象组合成树形结构来表现整体和部分的层次结构 装饰器模式Decorator 通过增加一个修饰对象来包裹原来的对象从而给原来的对象添加新的行为 适配器模式Adapter 允许两个接口不兼容的对象相互交互 代理模式Proxy 为另一个对象提供替代或者占位符 享元模式Flyweight 运用共享技术来有效地支持大量细粒度对象的复用以减少创建的对象的数量 ▐ 行为型Behavioral11种 负责对象间的高效沟通和职责委派。 迭代器模式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: PartA1console.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: Im not aware of the creators 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: Leafconst 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(LeafLeaf)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(LeafLeaf)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: ConcreteComponentconst 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 laicepSconst 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 IteratorT {current(): T; // 返回当前的元素next(): T; // 返回下一个元素key(): number; // 返回当前元素的keyvalid(): boolean; // 检测当前位置是否是有效的rewind(): void; // 将迭代器回退到第一个元素
}
interface Aggregator {getIterator(): Iteratorstring; // 获取外部迭代器
}
// 具体迭代器实现各种遍历算法。这些类在任何时候都存储当前遍历位置
class AlphabeticalOrderIterator implements Iteratorstring {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(): Iteratorstring {return new AlphabeticalOrderIterator(this);}public getReverseIterator(): Iteratorstring {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: Im doing something important. Subject: My state has just changed to: 6. Subject: Notifying observers... ConcreteObserverB: Reacted to the event.
subject.someBusinessLogic(); // Subject: Im 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: Im 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 ${(anystate).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 Originators state...
Originator: Im doing something important.
Originator: and my state has changed to: qXqxgTcLSCeLYdcgElOghOFhPGfMxoCaretaker: Saving Originators state...
Originator: Im doing something important.
Originator: and my state has changed to: iaVCJVryJwWwbipieensfodeMSWvUYCaretaker: Saving Originators state...
Originator: Im doing something important.
Originator: and my state has changed to: oSUxsOCiZEnohBMQEjwnPWJLGnwGmyCaretaker: Heres 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, lets rollback!Caretaker: Restoring state to: 2019-02-17 15:14:05 / (iaVCJVryJ...)
Originator: My state has changed to: iaVCJVryJwWwbipieensfodeMSWvUYClient: 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 itll do it)
a,b,c,d,eClient: Strategy is set to reverse sorting.
Context: Sorting data using the strategy (not sure how itll 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 anywaySame 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: Ill eat the ${request}.;}return super.handle(request);}
}
class SquirrelHandler extends AbstractHandler {public handle(request: string): string {if (request Nut) {return Squirrel: Ill eat the ${request}.;}return super.handle(request);}
}
class DogHandler extends AbstractHandler {public handle(request: string): string {if (request MeatBall) {return Dog: Ill 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 DogClient: Who wants a Nut?Squirrel: Ill eat the Nut.
Client: Who wants a Banana?Monkey: Ill eat the Banana.
Client: Who wants a Cup of coffee?Cup of coffee was left untouched.Subchain: Squirrel DogClient: Who wants a Nut?Squirrel: Ill 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等多种技术产品。 ¤ 拓展阅读 ¤ 3DXR技术 | 终端技术 | 音视频技术 服务端技术 | 技术质量 | 数据算法