主页 > 手机  > 

【设计模式】01-一文理解常用设计模式-“创建型模式”篇

【设计模式】01-一文理解常用设计模式-“创建型模式”篇
一、前言

最近在复习设计模式,撰写、整理了内容和代码片段,和大家一起交流学习。

设计模式是软件设计中常见问题的典型解决方案。

修改记录 更新内容更新时间第一版

250212

更新了对文章中的模式代码示范的解释250214

 

二、模式分类

模式可以根据其意图或目的来分类。常见的设计模式包括:

创建型模式提供创建对象的机制, 增加已有代码的灵活性和可复用性;

结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效;

行为型模式负责对象间的高效沟通和职责委派;

本篇文章介绍创建型模式,后续会更新其他两类设计模式。


三、创建型模式概述

创建型模式主要用于对象的创建过程,它隐藏了对象的创建逻辑,使得代码更具灵活性和可维护性。

四、常见创建型模式(配合代码) 1、单例模式(Singleton Pattern):

确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。

// 单例模式示例 const Singleton = (function () {    let instance;    function createInstance() {        const object = new Object({ name: 'Singleton Object' });        return object;   }    return {        getInstance: function () {            if (!instance) {                instance = createInstance();           }            return instance;       }   }; }()); // 使用示例 const instance1 = Singleton.getInstance(); const instance2 = Singleton.getInstance(); console.log(instance1 === instance2); // 输出: true 代码分析 立即执行函数(IIFE): 代码使用了一个立即执行函数 (function () { ... }()),这样可以创建一个独立的作用域,避免变量和函数泄露到全局作用域。 instance 变量: 在立即执行函数内部声明了一个变量 instance,初始值为 undefined。这个变量用于存储单例对象的实例。 createInstance 函数: 该函数用于创建单例对象的实例。它使用 new Object() 创建一个新对象,并传入一个包含 name 属性的对象字面量 { name: 'Singleton Object' },最后返回这个新对象。 返回对象: 立即执行函数返回一个包含 getInstance 方法的对象。这个对象就是外部可以访问的接口。 getInstance 方法: 该方法是获取单例对象实例的唯一途径。首先检查 instance 是否为 undefined(即是否已经创建了实例)。如果 instance 为 undefined,则调用 createInstance 函数创建一个新的实例,并将其赋值给 instance。最后返回 instance。这样,无论调用多少次 getInstance 方法,只要 instance 已经被创建,就会一直返回同一个实例。

代码运行结果

调用 Singleton.getInstance() 方法两次,分别将返回的实例存储在 instance1 和 instance2 中。使用 === 比较 instance1 和 instance2 是否为同一个对象。由于单例模式确保只有一个实例存在,所以 instance1 和 instance2 是同一个对象,比较结果为 true,并将结果打印到控制台。

2、工厂模式(Factory Pattern):

定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

简单理解:工厂模式就像一个工厂,根据不同的需求生产不同的产品。你只需要告诉工厂你需要什么,工厂就会帮你创建出来。

// 工厂模式示例 function CarFactory() {    this.createCar = function (type) {        let car;        if (type === 'sedan') {            car = new Sedan();       } else if (type === 'suv') {            car = new SUV();       }        car.drive = function () {            console.log(`Driving a ${this.constructor.name}`);       };        return car;   }; } ​//createCar 方法: //该方法接收一个 type 参数,用于指定要创建的汽车类型。 //根据 type 的值,使用 if-else 语句来决定创建哪种类型的汽车对象。如果 type 为 'sedan',则创建一个 Sedan 对象;如果 type 为 'suv',则创建一个 SUV 对象。 //为创建的汽车对象添加一个 drive 方法,该方法会在控制台打印出正在驾驶的汽车类型。这里使用 this.constructor.name 来获取汽车对象的构造函数名,从而得到汽车的类型。 //最后返回创建好的汽车对象。 function Sedan() {    this.type = 'Sedan'; } //这是一个简单的构造函数,用于创建轿车对象。在创建 Sedan 对象时,会给对象添加一个 type 属性,值为 'Sedan'。​ function SUV() {    this.type = 'SUV'; } ​//意思同上 // 使用示例 const factory = new CarFactory(); const sedan = factory.createCar('sedan'); const suv = factory.createCar('suv'); ​ sedan.drive(); // 输出: Driving a Sedan suv.drive();   // 输出: Driving a SUV

代码运行结果

创建一个 CarFactory 类的实例 factory。调用 factory.createCar('sedan') 方法创建一个轿车对象,并将其赋值给 sedan。调用 factory.createCar('suv') 方法创建一个 SUV 对象,并将其赋值给 suv。分别调用 sedan.drive() 和 suv.drive() 方法,会在控制台输出相应的驾驶信息,表明成功创建并使用了不同类型的汽车对象。

3、抽象工厂模式(Abstract Factory Pattern):

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

简单理解:就像一个超级工厂,能生产不同品牌的汽车系列产品。

// 抽象工厂模式示例 // 抽象工厂 function AbstractCarFactory() {    this.createEngine = function () {        throw new Error('This method must be overridden!');   };    this.createWheel = function () {        throw new Error('This method must be overridden!');   }; } //功能:抽象工厂定义了创建发动机和车轮的抽象方法。由于这是抽象工厂,这些方法并没有具体实现,而是抛出一个错误,提醒具体工厂必须重写这些方法。 //作用:为具体工厂提供了一个统一的接口,确保所有具体工厂都实现了创建发动机和车轮的功能。​ // 具体工厂:丰田工厂 function ToyotaFactory() {    AbstractCarFactory.call(this);    this.createEngine = function () {        return new ToyotaEngine();   };    this.createWheel = function () {        return new ToyotaWheel();   }; } //继承:使用 AbstractCarFactory.call(this) 继承了抽象工厂的属性和方法。 //方法实现:重写了 createEngine 方法,返回一个 ToyotaEngine 实例;重写了 createWheel 方法,返回一个 ToyotaWheel 实例。 ​ // 具体工厂:本田工厂 function HondaFactory() {    AbstractCarFactory.call(this);    this.createEngine = function () {        return new HondaEngine();   };    this.createWheel = function () {        return new HondaWheel();   }; } //​继承:同样继承了抽象工厂的属性和方法。 //方法实现:重写了 createEngine 方法,返回一个 HondaEngine 实例;重写了 createWheel 方法,返回一个 HondaWheel 实例。 // 丰田发动机 function ToyotaEngine() {    this.start = function () {        console.log('Toyota engine started');   }; } ​//功能:表示丰田发动机,有一个 start 方法,用于启动发动机并在控制台输出相应信息。 // 丰田车轮 function ToyotaWheel() {    this.rotate = function () {        console.log('Toyota wheel rotating');   //功能:表示丰田车轮,有一个 rotate 方法,用于模拟车轮转动并在控制台输出相应信息。}; } // 本田发动机 function HondaEngine() {    this.start = function () {        console.log('Honda engine started');   }; } //功能:表示本田发动机,有一个 start 方法,用于启动发动机并在控制台输出相应信息。 ​ // 本田车轮 function HondaWheel() {    this.rotate = function () {        console.log('Honda wheel rotating');   }; } ​//功能:表示本田车轮,有一个 rotate 方法,用于模拟车轮转动并在控制台输出相应信息。 // 使用示例 const toyotaFactory = new ToyotaFactory(); const toyotaEngine = toyotaFactory.createEngine(); const toyotaWheel = toyotaFactory.createWheel(); ​ toyotaEngine.start(); // 输出: Toyota engine started toyotaWheel.rotate(); // 输出: Toyota wheel rotating ​ const hondaFactory = new HondaFactory(); const hondaEngine = hondaFactory.createEngine(); const hondaWheel = hondaFactory.createWheel(); ​ hondaEngine.start(); // 输出: Honda engine started hondaWheel.rotate(); // 输出: Honda wheel rotating 代码运行结果 创建丰田工厂及部件:创建一个 ToyotaFactory 实例,使用该工厂创建丰田发动机和车轮,并调用它们的方法,输出相应信息。创建本田工厂及部件:创建一个 HondaFactory 实例,使用该工厂创建本田发动机和车轮,并调用它们的方法,输出相应信息。 4、建造者模式(Builder Pattern):

将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

简单理解:就像建造房子,有不同的建造步骤,最终可以建成不同风格的房子。

// 建造者模式示例 // 产品类:汽车 function Car() {    this.wheels = null;    this.engine = null;    this.color = null; ​    this.showInfo = function () {        console.log(`Car with ${this.wheels} wheels, ${this.engine} engine and ${this.color} color`);   }; } //​属性: //wheels:用于存储汽车的车轮数量,初始值为 null。 //engine:用于存储汽车的发动机类型,初始值为 null。 //color:用于存储汽车的颜色,初始值为 null。 //方法: //showInfo:该方法会将汽车的车轮数量、发动机类型和颜色信息拼接成字符串,并打印到控制台,方便查看汽车的具体配置。 // 建造者类 function CarBuilder() {    this.car = new Car(); ​    this.setWheels = function (wheels) {        this.car.wheels = wheels;        return this;   }; ​    this.setEngine = function (engine) {        this.car.engine = engine;        return this;   }; ​    this.setColor = function (color) {        this.car.color = color;        return this;   }; ​    this.build = function () {        return this.car;   }; } //​属性: //car:在构造函数中创建一个 Car 类的实例,后续的设置操作都是针对这个汽车对象进行的。 方法: //setWheels:接收一个 wheels 参数,将其赋值给 this.car.wheels,并返回 this(即当前 CarBuilder 实例),这样可以实现链式调用。 //setEngine:接收一个 engine 参数,将其赋值给 this.car.engine,同样返回 this 以支持链式调用。 //setColor:接收一个 color 参数,将其赋值给 this.car.color,也返回 this 用于链式调用。 //build:返回已经构建好的 this.car 对象,标志着汽车构建完成。 // 使用示例 const builder = new CarBuilder(); const car = builder   .setWheels(4)   .setEngine('V8')   .setColor('Red')   .build(); ​ car.showInfo(); // 输出: Car with 4 wheels, V8 engine and Red color

代码运行结果

创建一个 CarBuilder 类的实例 builder。通过链式调用 setWheels、setEngine 和 setColor 方法,依次为汽车设置车轮数量、发动机类型和颜色。调用 build 方法,得到最终构建好的 Car 对象,并将其赋值给 car。调用 car.showInfo() 方法,在控制台输出汽车的详细信息。

5、原型模式(Prototype Pattern):

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

简单理解:就像复印文件,有一个原始文件作为模板,然后可以复印出很多份一样的文件。

// 原型模式示例 const carPrototype = {    brand: 'Unknown',    model: 'Unknown',    start: function () {        console.log(`Starting the ${this.brand} ${this.model}`);   },    clone: function () {        const clone = Object.create(this);        return clone;   } }; //属性: //brand:初始值为 'Unknown',用于表示汽车的品牌。 //model:初始值为 'Unknown',用于表示汽车的型号。 //方法: //start:该方法会在控制台打印出启动当前汽车(根据 this.brand 和 this.model)的信息。这里的 this 指向调用该方法的对象。 //clone:使用 Object.create(this) 方法创建一个新对象,该新对象继承自当前原型对象(this)。这意味着新对象会拥有原型对象的所有属性和方法,并且对新对象属性的修改不会影响原型对象本身。最后返回这个克隆后的新对象。 ​ // 使用示例 const car1 = carPrototype.clone(); car1.brand = 'Toyota'; car1.model = 'Corolla'; ​ const car2 = carPrototype.clone(); car2.brand = 'Honda'; car2.model = 'Civic'; ​ car1.start(); // 输出: Starting the Toyota Corolla car2.start(); // 输出: Starting the Honda Civic

代码运行结果

创建 car1 对象: 调用 carPrototype.clone() 方法克隆原型对象,得到一个新的汽车对象 car1。分别为 car1 的 brand 和 model 属性赋值为 'Toyota' 和 'Corolla'。 创建 car2 对象: 同样调用 carPrototype.clone() 方法克隆原型对象,得到另一个新的汽车对象 car2。为 car2 的 brand 和 model 属性赋值为 'Honda' 和 'Civic'。 调用 start 方法: 分别调用 car1.start() 和 car2.start() 方法,由于 this 指向调用该方法的对象,所以会根据各自对象的 brand 和 model 属性输出相应的启动信息。


五、小结

设计模式在编程当中还是挺重要的,优点包括但不限于:代码复用性更高、可维护性更强、可扩展性更好。

有时间可以花点时间学习/复习一下,相信对我们的编程技术和编程思维会有很多进步~

标签:

【设计模式】01-一文理解常用设计模式-“创建型模式”篇由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“【设计模式】01-一文理解常用设计模式-“创建型模式”篇