问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

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

创作时间:
作者:
@小白创作中心

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

引用
CSDN
1.
https://m.blog.csdn.net/orbit4/article/details/145601038

设计模式是软件开发中解决常见问题的通用方案,其中创建型模式主要用于对象的创建过程,通过隐藏对象的创建逻辑来提升代码的灵活性和可维护性。本文将详细介绍单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式,并通过具体的代码示例帮助读者理解这些模式的实现方式和应用场景。

二、模式分类

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

  • 创建型模式:提供创建对象的机制,增加已有代码的灵活性和可复用性;
  • 结构型模式:介绍如何将对象和类组装成较大的结构,同时保持结构的灵活和高效;
  • 行为型模式:负责对象间的高效沟通和职责委派。

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

三、创建型模式概述

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

四、常见创建型模式(配合代码)

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;
    };
}

function Sedan() {
    this.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();
    };
}

function HondaFactory() {
    AbstractCarFactory.call(this);
    this.createEngine = function () {
        return new HondaEngine();
    };
    this.createWheel = function () {
        return new HondaWheel();
    };
}

function ToyotaEngine() {
    this.start = function () {
        console.log('Toyota engine started');
    };
}

function ToyotaWheel() {
    this.rotate = function () {
        console.log('Toyota wheel rotating');
    };
}

function HondaEngine() {
    this.start = function () {
        console.log('Honda engine started');
    };
}

function HondaWheel() {
    this.rotate = function () {
        console.log('Honda wheel rotating');
    };
}

// 使用示例
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`);
    };
}

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;
    };
}

// 使用示例
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
  • 通过链式调用 setWheelssetEnginesetColor 方法,依次为汽车设置车轮数量、发动机类型和颜色。
  • 调用 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;
    }
};

// 使用示例
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
  • 分别为 car1brandmodel 属性赋值为 'Toyota''Corolla'
  • 创建 car2 对象
  • 同样调用 carPrototype.clone() 方法克隆原型对象,得到另一个新的汽车对象 car2
  • car2brandmodel 属性赋值为 'Honda''Civic'
  • 调用 start 方法
  • 分别调用 car1.start()car2.start() 方法,由于 this 指向调用该方法的对象,所以会根据各自对象的 brandmodel 属性输出相应的启动信息。

五、小结

设计模式在编程当中还是挺重要的,优点包括但不限于:代码复用性更高、可维护性更强、可扩展性更好。有时间可以花点时间学习/复习一下,相信对我们的编程技术和编程思维会有很多进步~

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号