【设计模式】一文理解常用设计模式-“创建型模式”篇
创作时间:
作者:
@小白创作中心
【设计模式】一文理解常用设计模式-“创建型模式”篇
引用
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
。 - 通过链式调用
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;
}
};
// 使用示例
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
属性输出相应的启动信息。
五、小结
设计模式在编程当中还是挺重要的,优点包括但不限于:代码复用性更高、可维护性更强、可扩展性更好。有时间可以花点时间学习/复习一下,相信对我们的编程技术和编程思维会有很多进步~
热门推荐
资产负债表分析:一眼看穿企业财务状况的5个要点
企业培训讲课内容如何编写
三角梅为什么会卷叶,存在温度不适、光照太强、缺少水分等因素
柳宗元《晋问》:一篇赞美晋地山河与物产的文学佳作
如何巧妙地发群公告并吸引注意
从 Manus 的爆火看利用热词的引流技巧
数据分析行业:揭秘当今最炙手可热的职业领域
HDMI 2.0 是否支持 140Hz 刷新率?详细解析与兼容性探讨
HDMI 2.0和HDMI 2.1的区别
什么是人工智能(AI)?其在SaaS中的应用与未来趋势
细胞及其增殖、调控机制的发现历程
如何通过社保局官网查询个人账户缴费明细?
涨知识!贡菜到底是不是莴笋?还有哪些蔬菜是“亲戚”?
如何做好课前预习:七个方面的实用建议
揭秘!一日三餐如何科学摄入1200大卡
公司经营情况分析 - 了解你所投资公司的真实状况
智能体脂称硬件设计详解:从电源到数据传输的完整方案
从实验室看翡翠,如何鉴定真假?
深圳网站建设内容管理中的版权问题:如何避免侵权?
如何通过练习提升倒车技能?这些练习方法对驾驶安全有何影响?
如何选择合适的家居用品?这些用品有哪些潜在的优势和劣势?
江西省赣州市:加速“融湾” 展现高质量发展新势头
如何描写童年生活的地方?童年记事:如何生动描绘你儿时的乐园?!
无法连接服务器?这些原因和解决方法请收好
生命守护之门,带您揭开 ICU 的神秘面纱
学霸的高效预习法:三个基本原则让学习效率翻倍
Skype如何禁止陌生人私聊?
JWT揭秘:前后端安全与双Token策略全解析
企业人力资源管理系统的ER图包含哪些实体和关系?
如何勇于尝试新事物