轻松掌握设计模式-创建型模式
文/晨风不可依米 (2025.06.25)
程序设计模式-创建型模式
- 隐藏对象创建过程的逻辑。
- 非直接使用
new操作初始化对象。 - 具有代码复用性高、对象扩展性灵活等特点。
.
单例模式
- 单例模式:是指在创建对象过程中仅保存一个实例对象;再次创建对象,即直接使用该对象引用。
- 模式优缺点:
- 优点:只有一个实例对象,节省内存空间、提升访问速度等。
- 缺点:违背单一职责,无法构建多实例对象,需重构来解决。
- 适用场景:配置类对象,资源类对象、系统类对象,全局单一对象。
饿汉式单例实现
- 特点:无论是否使用单例对象,类对象加载时创建。
class Singleton {
// 在类加载时,初始化单例对象
private static instance: Singleton = new Singleton();
public static getInstance: Singleton {
return this.instance
}
// 禁止使用 new 来创建对象
private constructor () {}
}
懒汉式单例实现
- 特点:在首次调用时初始化单例对象。
class Singleton {
// 在类加载时,初始化单例对象
private static instance: Singleton | null = null;
public static getInstance: Singleton {
// 首次使用时动态创建
if (!this.instance) this.instance = new Singleton();
return this.instance;
}
// 禁止使用 new 来创建对象
private constructor () {}
}
工厂模式
- 工厂模式:是指将对象创建过程与对象使用过程分离,通过工厂类封装对象的创建逻辑,并返回创建对象。
- 模式优缺点:
- 优点:创建过程与使用过程分离,拓展与维护性好。
- 缺点:类对象众多,且关系复杂。
- 适用场景:条件式创建同质对象实例,或者组合多种非同质对象实例来构成完整服务功能对象。
简单工厂模式
- 定义产品接口声明,并实现具体产品类的封装过程。
- 定义工厂类,根据条件(产品类型)返回指定具体产品实例对象。
// 定义产品接口声明
interface Phone {
getPhoneID (): string
initBrowser(): void;
}
// 封装具体产品类对象
class IPhone6 implements Phone {
getPhoneID (): string {
return Math.random().toString().slice(2);
}
initBrowser () {
console.log('初始化浏览器')
}
}
class IPhone8 implements Phone {
getPhoneID (): string {
return Math.random().toString().slice(2);
}
initBrowser () {
console.log('初始化浏览器')
}
}
// 定义工厂类,提供条件返回具体产品实例对象
class IPhoneFactory {
createPhone (type: string): Phone {
if (type === 'iphone6') {
return new IPhone6();
} else if (type === 'iphonne8') {
return new IPhone8();
} else {
throw new Error(`工厂类不存在 ${type} 类型手机,无法创建`);
}
}
}
工厂方法模式
- 定义抽象产品类、抽象工厂类,规范类对象的方法接口,并交由具体类来实现抽象方法。
- 定义具体产品类、具体工厂类,实现具体类对象的封装过程,以及实现抽象方法功能逻辑。
- 特点:具体工厂类创建同质单一对象实例,强调创建同一工厂类型的对象(比如苹果手机,有i6、i9)。
// 定义抽象产品类
abstract class Phone {
// 公共方法
public getPhoneID (): string {
if (!this.phoneID) return null;
return this.phoneID;
}
// 抽象方法
abstract usePhone(): void;
abstract useSMS(): void;
}
// 实现产品类;如苹果手机
class IPhone extends Phone {
// 实现抽象方法具体逻辑
public usePhone(): void {
console.log('使用苹果手机电话功能')
}
public usePhone(): void {
console.log('使用苹果手机短讯功能')
}
}
// 实现产品类;如安卓手机
class Android extends Phone {
// 实现抽象方法具体逻辑
public usePhone(): void {
console.log('使用安卓手机电话功能')
}
public usePhone(): void {
console.log('使用安卓手机短讯功能')
}
}
// 定义抽象工厂类
abstract class PhoneFactory {
abstract createPhone(): Phone
}
// 实现具体工厂类,如苹果手机工厂
class IPhoneFactory extends PhoneFactory {
public createPhone(): Phone {
return new IPhone();
}
}
// 实现具体工厂类,如安卓手机工厂
class AndroidFactory extends PhoneFactory {
public createPhone(): Phone {
return new Android();
}
}
// 应用场景
const AndroidFactoryInstance = new AndroidFactory();
const AndroidPhone = AndroidFactoryInstance.createPhone();
AndroidPhone.usePhone();
抽象工厂模式
- 定义抽象产品类、抽象工厂类,规范类对象的方法接口,并交由具体类来实现抽象方法。
- 定义具体产品类、具体工厂类,实现具体类对象的封装过程,以及实现抽象方法功能逻辑。
- 特点:具体工厂类创建非同质单一对象实例,强调创建多个不同类型的产品类来组合构建完整功能的产品(如套餐菜单,饮料有咖啡、雪碧)。
// 定义抽象饮料类
abstract class Drink {
abstract getDrinkInfo(): string;
}
// 实现具体饮料类(咖啡)
class Coffee extends Drink {
public getDrinkInfo() {
console.log('这是一杯咖啡');
}
}
// 实现具体饮料类(雪碧)
class Sprite extends Drink {
public getDrinkInfo() {
console.log('这是一杯雪碧');
}
}
// 定义抽象面包类
abstract class Bread {
abstract getBreadInfo(): string;
}
// 定义具体面包类(法棍)
class Baguette extends Bread {
public getBreadInfo() {
console.log('这是一条法棍');
}
}
// 定义具体面包类(肉包子)
class MeatBun extends Bread {
public getBreadInfo() {
console.log('这是一个肉包子');
}
}
// 定义抽象面条类
abstract class Noodles {
abstract getNoodlesInfo(): string;
}
// 实现具体面条类(意大利面)
class Pasta extends Noodles {
public getNoodlesInfo() {
console.log('这是一碗意大利面');
}
}
// 实现具体面条类(河粉)
class RiceNoodles extends Noodles {
public getNoodlesInfo() {
console.log('这是一碗河粉');
}
}
// 定义抽象工厂类
abstract class MenuFactory {
abstract createDrink(): Drink;
abstract createBread(): Bread;
abstract createNoodles(): Noodles;
}
// 实现具体工厂类(中国套餐)
class ChinaMenuFactory extends MenuFactory {
public createDrink(): Drink {
return new Sprite();
}
public createBread(): Bread {
return new MeatBun();
}
public createNoodles(): Noodles {
return new RiceNoodles();
}
}
// 实现具体工厂类(外国套餐)
class ForeignMenuFactory extends MenuFactory {
public createDrink(): Drink {
return new Coffee();
}
public createBread(): Bread {
return new Baguette();
}
public createNoodles(): Noodles {
return new Pasta();
}
}
// 查看套餐信息
function getMenuProductInfo (factory: MenuFactory) [
const drink = chinaMenu.createDrink();
const bread = chinaMenu.createBread();
const noodles = chinaMenu.createNoodles()
drink.getDrinkInfo()
bread.getBreadInfo()
noodles.getNoodlesInfo()
}
// 点选中国套餐
const chinaMenu = new ChinaMenuFactory();
getMenuProductInfo(chinaMenu);
建造者(生成器)模式
- 建造者模式:通过选择多变的部件类,并按相对稳定的构建流程顺序完成复杂对象的创建。
- 模式优缺点:
- 优点:类对象构建过程分离,并隐藏构建过程,且灵活控制。
- 缺点:类与对象多,且关系复杂。部件类选择方式较少时,代码量较大。
- 适用场景:产品类中存在部件选择或复杂对象构建流程控制等创建场景。
经典案例
- 定义部件类,以供产品类选择所需的部件。
- 定义产品类,提供部件替换的方法(
set**)。 - 定义建造者类接口声明,规范约束创建部件类的方法(
build**)。 - 定义具体建造者类,实现部件类的选择逻辑,以及访问产品类对象的方法。
- 定义指导类,不关心构建内容,只关心构建顺序和方式。
// 部件类类型声明
interface ProductOpt {
name: string
price: number
}
// 定义部件类(饮料)
class Drink {
public name: string;
public price: number;
constructor (opt: ProductOpt) {
this.price = opt.price;
this.name = opt.name;
}
}
// 定义部件类(面包)
class Bread {
public name: string;
public price: number;
constructor (opt: ProductOpt) {
this.price = opt.price;
this.name = opt.name;
}
}
// 定义部件类(面食)
class Noodles {
public name: string;
public price: number;
constructor (opt: ProductOpt) {
this.price = opt.price;
this.name = opt.name;
}
}
// 定义产品类
class Menu {
private drink: Drink;
private bread: Bread;
private noodles: Noodles;
public setDrink(drink: Drink): void {
this.drink = drink;
}
public setBread(bread: Bread): void {
this.bread = bread;
}
public setNoodles(noodles: Noodles): void {
this.noodles = noodles;
}
public getInfo() {
return {
drink: this.drink ?? null,
bread: this.bread ?? null,
noodles: this.noodles ?? null
}
}
}
// 定义建造者类接口声明
interface MenuBuilder {
buildDrink(): void;
buildBread(): void;
buildNoodles(): void;
getMenu(): Menu;
}
// 定义具体建造者类(套餐A: 咖啡、法棍、意大利面)
class MenuABuilder implements MenuBuilder {
private menu : Menu;
constructor() {
this.menu = new Menu();
}
buildDrink(): void {
const drink = new Drimk({ name: '咖啡', price: 10 });
this.menu.setDrink(drink);
}
buildBread(): void {
const bread = new Bread({ name: '法棍', price: 5 });
this.menu.setBread(bread);
}
buildNoodles(): void {
const noodles = new Noodles({ name: '意大利面', price: 25 });
this.menu.setNoodles(noodles);
}
getMenu(): Menu {
return this.menu;
}
}
// 定义具体建造者类(套餐B: 雪碧、肉包、河粉)
class MenuBBuilder implements MenuBuilder {
private menu : Menu;
constructor() {
this.menu = new Menu();
}
buildDrink(): void {
const drink = new Drimk({ name: '雪碧', price:3 });
this.menu.setDrink(drink);
}
buildBread(): void {
const bread = new Bread({ name: '肉包', price: 2 });
this.menu.setBread(bread);
}
buildNoodles(): void {
const noodles = new Noodles({ name: '河粉', price: 15 });
this.menu.setNoodles(noodles);
}
getMenu(): Menu {
return this.menu;
}
}
// 定义指导类(下单流程以及费用统计)
class MenuDirector {
private builder: MenuBuilder
constructor (builder: MenuBuilder) {
this.builder = builder;
}
// 下单流程
public submitOrder () {
this.builder.buildDrink();
this.builder.buildBread();
this.builder.buildNoodles();
}
// 费用统计
public computedFee() {
const { drink, bread, noodles } = this.getMenuInfo();
return [drink, bread, noodles].reduce((sum, product => sum + product.price, 0);
}
// 获取套餐信息
public getMenuInfo () {
const menu = this.builder.getMenu();
return menu.getInfo();
}
}
// 选择套餐A
const menuA = new MenuABuilder();
const orderA = new MenuDirector(menuA);
orderA.submitOrder();
console.log(orderA.comptedFee())
原型模式
- 原型模式;基于当前对象(内含自我拷贝
clone方法)为模板,减少创建对象过程(构造对象、初始化属性和方法)的性能消耗, - 模式优缺点:
- 优点:减少创建对象过程的内存占用,复制现有副本修改。
- 缺点:重点关注对象的结构复杂性,以便采用浅拷贝或深拷贝来克隆对象为模板。
- 适用场景:频繁创建建对象带来巨大性能消耗(对象复杂或多级无限嵌套)。
浅拷贝原型模式
- 简单对象结构(少数属性和方法);浅拷贝克隆对象一层属性和方法等内容,对象的引用属性或方法修改,源体与副本对象会造成一改全改。
/** 浅拷贝 */
function shallowClone<T>(input: T): T {
if (Array.isArray(input)) {
return input.slice() as any;
} else if (input && typeof input === 'object') {
return Object.assign(
Object.create(Object.getPrototypeOf(input)),
input
);
}
return input;
}
/** 原型对象类型声明 */
interface Prototype<T> {
/** 自我拷贝clone方法 */
clone(): T;
}
interface HumanOption {
name: string;
age?: string;
}
class Human implements Prototype<Human> {
constrctor (option) {
const keys = Object.keys(option);
for (const key of keys) {
this[key] = option[key]l
}
}
/** 自我拷贝clone方法 */
clone(option) {
return new Human(shallowClone(this.option))
}
}
深拷贝原型模式
- 复杂对象结构(庞大属性和方法);深拷贝克隆对象所有属性和方法,对象的引用属性或方法修改,源体与副本对象互不影响。
function deepClone<T>(input: T, weakMap = new WeakMap()): T {
// 基本类型或函数
if (input === null || typeof input !== 'object') {
return input;
}
// 防止循环引用
if (weakMap.has(input as object)) {
return weakMap.get(input as object);
}
/** 各种类型对象的深拷贝处理 */
// Date
if (input instanceof Date) {
return new Date(input) as any;
}
// RegExp
if (input instanceof RegExp) {
return new RegExp(input) as any;
}
// Map
if (input instanceof Map) {
const result = new Map();
weakMap.set(input, result);
input.forEach((v, k) => {
result.set(deepClone(k, weakMap), deepClone(v, weakMap));
});
return result as any;
}
// Set
if (input instanceof Set) {
const result = new Set();
weakMap.set(input, result);
input.forEach((v) => {
result.add(deepClone(v, weakMap));
});
return result as any;
}
// Array
if (Array.isArray(input)) {
const result: any[] = [];
weakMap.set(input, result);
input.forEach((item, idx) => {
result[idx] = deepClone(item, weakMap);
});
return result as any;
}
/** 记录引用缓存 */
const result = Object.create(Object.getPrototypeOf(input));
weakMap.set(input, result);
for (const key of Object.keys(input)) {
(result as any)[key] = deepClone((input as any)[key], weakMap);
}
return result;
}
/** 原型对象类型声明 */
interface Prototype<T> {
/** 自我拷贝clone方法 */
clone(): T;
}
interface HumanOption {
name: string;
age?: string;
}
class Human implements Prototype<Human> {
constrctor (option) {
const keys = Object.keys(option);
for (const key of keys) {
this[key] = option[key]l
}
}
/** 自我拷贝clone方法 */
clone(option) {
return new Human(deepClone(this.option))
}
}
文章收获
- 如果觉得对你有所帮助,请点下“推荐”吧!
- 如果担心文忘记章地址,请点下“收藏”吧!
- 如果对博主文章内容喜欢,可进行“关注”博主,更好地获悉最新文章内容。

浙公网安备 33010602011771号