设计模式(创建型)

什么是设计模式?

模式是一种可重用的解决方案,用于解决在特定环境中反复出现的问题;

设计模式则是这类解决方案在软件工程中的应用,它是一套经过验证的、针对面向对象软件设计中常见问题的通用模板。

设计模式的目的

  1. 提高代码的可重用性:通过使用设计模式,开发者可以复用经过验证的解决方案,而不必每次遇到相似问题时都从头开始设计。
  2. 提高代码的可维护性:设计模式有助于写出清晰和有组织的代码,这使得代码更容易理解和修改。
  3. 促进良好的编程实践:设计模式鼓励开发者遵循软件工程的最佳实践,如“封装变化点”、“针对接口编程而不是实现编程”等。

设计模式的分类

设计模式通常分为以下三大类:

  1. 创建型模式:这些模式处理对象的创建过程,隐藏创建逻辑而不是直接使用new运算符实例化对象。这包括单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式等。

  2. 结构型模式:这些模式主要关注类和对象之间的组合,用于形成更大的结构。这包括适配器模式、桥接模式、组合模式、装饰器模式、门面模式、享元模式、代理模式等。

  3. 行为型模式:这些模式主要关注对象之间的通信,它们描述了对象和类如何交互以及分配职责。这包括责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式等。

学习设计模式的前置条件

了解基本的软件设计原则,如单一职责原则(SRP)、开闭原则(OCP)、依赖倒置原则(DIP)等。这些原则是设计模式的理论基础,这里不多赘述。

创建型模式

由于设计模式篇幅过于辽阔,本片文章只讲创建型模式

1.单例模式

使用场景:日志记录器、数据库连接池,全局配置管理器等,需要确保某个类只有一个实例,并在整个应用程序中共享该实例。

解决问题:通过单例模式,确保一个类只有一个实例,并提供一个全局访问点访问该实例。

// 单例类
class Logger {
    private static instance: Logger;

    private constructor() {
        // 私有化构造函数,防止外部实例化
    }

    public static getInstance(): Logger {
        if (!Logger.instance) {
            Logger.instance = new Logger();
        }
        return Logger.instance;
    }

    public log(message: string): void {
        console.log(`[LOG]: ${message}`);
    }
}

// 客户端代码
const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();

logger1.log("This is the first log.");  // 输出: [LOG]: This is the first log.
logger2.log("This is the second log."); // 输出: [LOG]: This is the second log.

console.log(logger1 === logger2); // 输出: true,证明两者是同一个实例
  • 适用场景:需要保证类在整个系统中只有一个实例,且实例需要被全局共享时。

  • 优点:控制实例数量,节省资源,避免重复创建相同对象。

2.原型模式

场景:游戏角色属性克隆

不使用设计模式

不使用原型模式时,我们通常需要手动创建一个新的对象,并将每个属性逐个复制。

class Player {
    public name: string;
    public level: number;
    public abilities: string[];

    constructor(name: string, level: number, abilities: string[]) {
        this.name = name;
        this.level = level;
        this.abilities = abilities;
    }

    public describe(): string {
        return `Player: ${this.name}, Level: ${this.level}, Abilities: ${this.abilities.join(", ")}`;
    }
}

// 客户端代码
const originalPlayer = new Player("Warrior", 10, ["Sword Mastery", "Shield Block"]);

// 手动克隆角色
const clonedPlayer = new Player(
    originalPlayer.name,
    originalPlayer.level,
    [...originalPlayer.abilities] // 需要显式拷贝数组,避免引用同一个数组
);

console.log(clonedPlayer.describe());
// 输出: Player: Warrior, Level: 10, Abilities: Sword Mastery, Shield Block

使用原型模式

// 原型接口
interface GameCharacter extends Prototype {
    clone(): GameCharacter;
}

// 具体原型类:游戏角色
class Player implements GameCharacter {
    public name: string;
    public level: number;
    public abilities: string[];

    constructor(name: string, level: number, abilities: string[]) {
        this.name = name;
        this.level = level;
        this.abilities = abilities;
    }

    public clone(): Player {
        return new Player(this.name, this.level, [...this.abilities]);
    }

    public describe(): string {
        return `Player: ${this.name}, Level: ${this.level}, Abilities: ${this.abilities.join(", ")}`;
    }
}

// 客户端代码
const originalPlayer = new Player("Warrior", 10, ["Sword Mastery", "Shield Block"]);
const clonedPlayer = originalPlayer.clone();

console.log(clonedPlayer.describe());
// 输出: Player: Warrior, Level: 10, Abilities: Sword Mastery, Shield Block

优点:

  1. 简化克隆逻辑:克隆对象时不需要关注每个属性的具体实现。

  2. 代码维护更简单:如果 Player 类增加了新的属性,我们只需修改 clone() 方法,而不必在每次手动克隆时都更新逻辑。

  3. 减少代码重复:克隆逻辑集中在 clone() 方法中,避免在客户端代码中反复编写属性复制的代码。

总结

不使用设计模式时,手动复制每个属性不仅容易出错,还可能导致代码冗长和难以维护。尤其当类的属性较多或者可能在未来发生变化时,手动复制每个属性的成本会增加。

3.建造者模式

场景:创造一个复杂的房屋对象

不使用设计模式
class House {
    public type: string;          // 房屋类型
    public floors: number;        // 楼层数量
    public hasGarden: boolean;    // 是否有花园
    public hasPool: boolean;      // 是否有游泳池
    public hasGarage: boolean;    // 是否有车库
    public color: string;         // 房屋颜色
    public area: number;          // 房屋面积(平方米)
    public address: string;       // 房屋地址
    public numOfWindows: number;  // 窗户数量
    public numOfDoors: number;    // 门的数量

    constructor(
        type: string,
        floors: number,
        hasGarden: boolean,
        hasPool: boolean,
        hasGarage: boolean,
        color: string,
        area: number,
        address: string,
        numOfWindows: number,
        numOfDoors: number
    ) {
        this.type = type;
        this.floors = floors;
        this.hasGarden = hasGarden;
        this.hasPool = hasPool;
        this.hasGarage = hasGarage;
        this.color = color;
        this.area = area;
        this.address = address;
        this.numOfWindows = numOfWindows;
        this.numOfDoors = numOfDoors;
    }

    public describe(): string {
        return `House Type: ${this.type}, Floors: ${this.floors}, Garden: ${this.hasGarden}, Pool: ${this.hasPool}, Garage: ${this.hasGarage}, Color: ${this.color}, Area: ${this.area}, Address: ${this.address}, Windows: ${this.numOfWindows}, Doors: ${this.numOfDoors}`;
    }
}

// 客户端代码:手动构建复杂对象
const house = new House(
    "Villa",
    3,
    true,
    true,
    true,
    "White",
    250,
    "123 Main St",
    10,
    5
);

console.log(house.describe());
// 输出: House Type: Villa, Floors: 3, Garden: true, Pool: true, Garage: true, Color: White, Area: 250, Address: 123 Main St, Windows: 10, Doors: 5
不使用设计模式的缺点:
  1. 构造函数过于复杂:有10个参数,调用时容易出错。

  2. 参数顺序问题:必须严格按照参数顺序传递,增加了出错的风险,尤其是多个参数类型相同时。

  3. 难以扩展:如果要增加更多的属性,构造函数将变得更加臃肿,维护性差。

使用建造者模式

class House {
    public type: string;          // 房屋类型
    public floors: number;        // 楼层数量
    public hasGarden: boolean;    // 是否有花园
    public hasPool: boolean;      // 是否有游泳池
    public hasGarage: boolean;    // 是否有车库
    public color: string;         // 房屋颜色
    public area: number;          // 房屋面积(平方米)
    public address: string;       // 房屋地址
    public numOfWindows: number;  // 窗户数量
    public numOfDoors: number;    // 门的数量

    constructor() {
        this.type = "";
        this.floors = 0;
        this.hasGarden = false;
        this.hasPool = false;
        this.hasGarage = false;
        this.color = "";
        this.area = 0;
        this.address = "";
        this.numOfWindows = 0;
        this.numOfDoors = 0;
    }

    public describe(): string {
        return `House Type: ${this.type}, Floors: ${this.floors}, Garden: ${this.hasGarden}, Pool: ${this.hasPool}, Garage: ${this.hasGarage}, Color: ${this.color}, Area: ${this.area}, Address: ${this.address}, Windows: ${this.numOfWindows}, Doors: ${this.numOfDoors}`;
    }
}

class HouseBuilder {
    private house: House;

    constructor() {
        this.house = new House();
    }

    public setType(type: string): HouseBuilder {
        this.house.type = type;
        return this;
    }

    public setFloors(floors: number): HouseBuilder {
        this.house.floors = floors;
        return this;
    }

    public setGarden(hasGarden: boolean): HouseBuilder {
        this.house.hasGarden = hasGarden;
        return this;
    }

    public setPool(hasPool: boolean): HouseBuilder {
        this.house.hasPool = hasPool;
        return this;
    }

    public setGarage(hasGarage: boolean): HouseBuilder {
        this.house.hasGarage = hasGarage;
        return this;
    }

    public setColor(color: string): HouseBuilder {
        this.house.color = color;
        return this;
    }

    public setArea(area: number): HouseBuilder {
        this.house.area = area;
        return this;
    }

    public setAddress(address: string): HouseBuilder {
        this.house.address = address;
        return this;
    }

    public setNumOfWindows(numOfWindows: number): HouseBuilder {
        this.house.numOfWindows = numOfWindows;
        return this;
    }

    public setNumOfDoors(numOfDoors: number): HouseBuilder {
        this.house.numOfDoors = numOfDoors;
        return this;
    }

    public build(): House {
        return this.house;
    }
}

// 客户端代码:使用建造者模式构建对象
const builder = new HouseBuilder();
const house = builder
    .setType("Villa")
    .setFloors(3)
    .setGarden(true)
    .setPool(true)
    .setGarage(true)
    .setColor("White")
    .setArea(250)
    .setAddress("123 Main St")
    .setNumOfWindows(10)
    .setNumOfDoors(5)
    .build();

console.log(house.describe());
// 输出: House Type: Villa, Floors: 3, Garden: true, Pool: true, Garage: true, Color: White, Area: 250, Address: 123 Main St, Windows: 10, Doors: 5
使用建造者模式的优点:
  1. 代码更简洁清晰:每个属性的设置是显式的,顺序无关,客户端代码更易读,容易理解正在设置哪些属性。

  2. 降低出错风险:不需要记住参数的顺序和类型,链式调用使得代码更具有自描述性。

  3. 高度灵活:可以按需设置某些属性,而无需一次性传入所有属性值,灵活性高,适应不同的对象构建需求。

  4. 扩展性好:如果将来需要为House类添加新属性,只需在HouseBuilder中增加相应的设置方法,原有客户端代码不需要修改。

  5. 减少冗长构造函数:避免了长长的构造函数参数列表,尤其是当类的属性较多时,建造者模式能显著简化对象的创建过程。

总结

使用建造者模式构建拥有多个属性的复杂对象时,能够显著提高代码的可读性、可维护性和灵活性,减少出错的可能性。特别是在面对具有多个可选属性的大型对象时,建造者模式是一种非常合适的设计模式。

工厂方法模式

场景:订单处理系统中,不同类型的产品可能需要不同的处理方式。实物商品可能需要发货,而数字商品需要生成下载链接。

不使用工厂方法模式

// 订单处理系统中的普通订单
class RegularOrder {
  process() {
    console.log('处理普通订单');
    // 普通订单的处理逻辑
  }
}

// 订单处理系统中的会员订单
class MemberOrder {
  process() {
    console.log('处理会员订单');
    // 会员订单的处理逻辑
  }
}

// 订单处理类
class OrderProcessor {
  processOrder(orderType: string) {
    let order;
    if (orderType === 'regular') {
      order = new RegularOrder();
    } else if (orderType === 'member') {
      order = new MemberOrder();
    } else {
      throw new Error('Unknown order type');
    }

    order.process(); // 处理订单
  }
}

// 测试
const orderProcessor = new OrderProcessor();
orderProcessor.processOrder('regular'); // 处理普通订单
orderProcessor.processOrder('member');  // 处理会员订单
缺点:
  1. 扩展性差:每次新增一个新的订单类型,都需要修改 OrderProcessor 类,添加新的 if-else 分支,违反了 开闭原则(OCP)。

  2. 扩展困难:随着订单类型的增多,代码的维护和扩展将变得复杂且容易出错。

  3. 订单类型的实例化集中在 OrderProcessor:这个类不仅负责处理订单,还负责根据类型决定创建哪种订单对象,违反了单一职责原则。

使用工厂方法模式

// 订单接口
interface Order {
    processOrder(): string;
}

// 普通订单类
class RegularOrder implements Order {
    public processOrder(): string {
        return "处理普通订单";
    }
}

// 会员订单类
class MembershipOrder implements Order {
    public processOrder(): string {
        return "处理会员订单";
    }
}

// 工厂接口
interface OrderFactory {
    createOrder(): Order;
}

// 普通订单工厂类
class RegularOrderFactory implements OrderFactory {
    public createOrder(): Order {
        return new RegularOrder();
    }
}

// 会员订单工厂类
class MembershipOrderFactory implements OrderFactory {
    public createOrder(): Order {
        return new MembershipOrder();
    }
}

// 客户端代码
function orderProcessor(factory: OrderFactory): void {
    const order = factory.createOrder();
    console.log(order.processOrder());
}

// 使用工厂方法模式创建不同类型的订单
const regularOrderFactory = new RegularOrderFactory();
const membershipOrderFactory = new MembershipOrderFactory();

orderProcessor(regularOrderFactory); // 输出: 处理普通订单
orderProcessor(membershipOrderFactory); // 输出: 处理会员订单
工厂方法模式的优点
  • 将对象创建推迟到子类

    • OrderFactory 接口和具体的工厂类(RegularOrderFactoryMembershipOrderFactory)负责决定具体创建哪种类型的订单,而客户端代码(orderProcessor 函数)只关心如何处理订单,而不需要了解具体的创建细节。

  • 扩展性

    • 如果需要添加新的订单类型,只需新增一个新的订单类和相应的工厂类。客户端代码无需修改,可以继续使用新的工厂类创建新的订单类型。

  • 低耦合

    • 客户端代码不直接依赖于具体的订单类,而是依赖于工厂接口,这减少了代码的耦合度,提高了系统的灵活性和可维护性。

5.抽象工厂模式

场景:假设我们有一个支付处理系统,支持不同的支付方式,如信用卡和银行转账。每种支付方式都有自己的验证逻辑和交易处理逻辑。在不使用设计模式的情况下,通常会在客户端代码中通过 if-else 判断支付类型来处理不同支付方式。

不使用设计模式
// 信用卡支付类
class CreditCardPayment {
    public validateCard(): void {
        console.log("验证信用卡...");
    }

    public processPayment(): void {
        console.log("处理信用卡支付...");
    }
}

// 银行转账支付类
class BankTransferPayment {
    public validateAccount(): void {
        console.log("验证银行账户...");
    }

    public processPayment(): void {
        console.log("处理银行转账支付...");
    }
}

// 客户端代码
class PaymentProcessor {
    public processPayment(paymentType: string): void {
        if (paymentType === "CreditCard") {
            const payment = new CreditCardPayment();
            payment.validateCard();
            payment.processPayment();
        } else if (paymentType === "BankTransfer") {
            const payment = new BankTransferPayment();
            payment.validateAccount();
            payment.processPayment();
        } else {
            throw new Error("未知的支付类型");
        }
    }
}

// 客户端代码示例
const processor = new PaymentProcessor();
processor.processPayment("CreditCard");  // 输出:验证信用卡... 处理信用卡支付...
processor.processPayment("BankTransfer"); // 输出:验证银行账户... 处理银行转账支付...
缺点:
  1. 扩展性差:如果未来添加新的支付方式,例如移动支付(如微信支付或支付宝),需要修改 PaymentProcessor 类的代码,违反了开闭原则(OCP)。
  2. 代码冗长且难以维护:随着支付方式的增加,if-else 分支的数量也会增多,客户端代码将变得复杂且难以维护。
  3. 职责混乱PaymentProcessor 类不仅负责处理支付,还负责不同支付方式的实例化,这违反了单一职责原则。

使用抽象工厂模式

// 支付接口
interface Payment {
    validate(): void;
    processPayment(): void;
}

// 信用卡支付实现
class CreditCardPayment implements Payment {
    public validate(): void {
        console.log("验证信用卡...");
    }

    public processPayment(): void {
        console.log("处理信用卡支付...");
    }
}

// 银行转账支付实现
class BankTransferPayment implements Payment {
    public validate(): void {
        console.log("验证银行账户...");
    }

    public processPayment(): void {
        console.log("处理银行转账支付...");
    }
}

// 抽象支付工厂接口
interface PaymentFactory {
    createPayment(): Payment;
}

// 信用卡支付工厂
class CreditCardPaymentFactory implements PaymentFactory {
    public createPayment(): Payment {
        return new CreditCardPayment();
    }
}

// 银行转账支付工厂
class BankTransferPaymentFactory implements PaymentFactory {
    public createPayment(): Payment {
        return new BankTransferPayment();
    }
}

// 客户端代码
class PaymentProcessor {
    private factory: PaymentFactory;

    constructor(factory: PaymentFactory) {
        this.factory = factory;
    }

    public processPayment(): void {
        const payment = this.factory.createPayment();
        payment.validate();
        payment.processPayment();
    }
}

// 使用抽象工厂模式处理支付
const creditCardFactory = new CreditCardPaymentFactory();
const bankTransferFactory = new BankTransferPaymentFactory();

const creditCardProcessor = new PaymentProcessor(creditCardFactory);
creditCardProcessor.processPayment();  // 输出:验证信用卡... 处理信用卡支付...

const bankTransferProcessor = new PaymentProcessor(bankTransferFactory);
bankTransferProcessor.processPayment(); // 输出:验证银行账户... 处理银行转账支付...
优点总结:
  1. 扩展灵活性:如果要添加新的订单类型,比如国际订单,只需新增一个 InternationalOrder 类和 InternationalOrderFactory,而无需修改现有代码。
  2. 低耦合性:客户端代码不直接依赖具体的订单类,只依赖工厂接口,订单的创建逻辑被封装在具体的工厂中。
  3. 更好的维护性:当订单处理逻辑变更时,只需修改相关的订单类或工厂类,其他部分无需调整。

工厂方法模式和抽象工厂模式的差异

抽象工厂模式工厂方法模式在某些场景下看起来非常相似,因为它们都是用于创建对象的设计模式,且都通过定义接口或抽象类来将具体类的创建延迟到子类中。不过,它们之间有一些重要的区别,主要体现在它们的用途、结构和复杂性上。

区别概述:

  1. 工厂方法模式
    • 目的:工厂方法模式的核心是定义一个创建对象的接口,由子类决定要实例化的具体类。它只解决一个具体对象的创建问题。
    • 重点:专注于通过继承来控制单一对象的创建。一个类只负责创建某种对象。
    • 使用场景:当一个类无法预知要实例化的具体类型时,使用工厂方法模式可以将对象创建推迟到子类中进行。
  2. 抽象工厂模式
    • 目的:抽象工厂模式用于创建多个相关对象的家族,而不是一个单独的对象。它提供一个创建一系列相关或相互依赖对象的接口,而不指定具体的类。
    • 重点:它不仅仅是创建一个对象,而是创建多个相关联的对象,这些对象通常属于一个“产品族”。
    • 使用场景:当系统需要创建多个不同类型的对象,且这些对象是相关联的时,抽象工厂模式可以确保它们的兼容性。

举例说明

工厂方法模式:

问题:你要创建一类产品,但具体是哪种产品在运行时才知道。例如,创建一种支付方式(信用卡、银行转账等)。

// 支付接口
interface Payment {
    processPayment(): void;
}

// 工厂方法接口
abstract class PaymentFactory {
    public abstract createPayment(): Payment;
}

// 具体支付类
class CreditCardPayment implements Payment {
    public processPayment(): void {
        console.log("处理信用卡支付");
    }
}

class BankTransferPayment implements Payment {
    public processPayment(): void {
        console.log("处理银行转账支付");
    }
}

// 具体工厂类
class CreditCardPaymentFactory extends PaymentFactory {
    public createPayment(): Payment {
        return new CreditCardPayment();
    }
}

class BankTransferPaymentFactory extends PaymentFactory {
    public createPayment(): Payment {
        return new BankTransferPayment();
    }
}

// 客户端使用
const factory: PaymentFactory = new CreditCardPaymentFactory();
const payment: Payment = factory.createPayment();
payment.processPayment(); // 输出: 处理信用卡支付

要点:工厂方法模式只处理创建单个产品对象,且通过继承来实现产品的创建控制。

抽象工厂模式:

问题:你要创建多个产品,这些产品必须属于同一个产品家族。例如,一个 UI 工具包可能同时创建按钮和文本框,这些控件必须保持一致的外观风格(例如,Windows 风格或 Mac 风格)。

// 抽象产品A
interface Button {
    render(): void;
}

// 抽象产品B
interface TextBox {
    render(): void;
}

// 具体产品A
class WindowsButton implements Button {
    public render(): void {
        console.log("渲染Windows风格的按钮");
    }
}

// 具体产品B
class WindowsTextBox implements TextBox {
    public render(): void {
        console.log("渲染Windows风格的文本框");
    }
}

// 具体产品A
class MacButton implements Button {
    public render(): void {
        console.log("渲染Mac风格的按钮");
    }
}

// 具体产品B
class MacTextBox implements TextBox {
    public render(): void {
        console.log("渲染Mac风格的文本框");
    }
}

// 抽象工厂
interface UIComponentFactory {
    createButton(): Button;
    createTextBox(): TextBox;
}

// 具体工厂(Windows风格组件工厂)
class WindowsUIFactory implements UIComponentFactory {
    public createButton(): Button {
        return new WindowsButton();
    }

    public createTextBox(): TextBox {
        return new WindowsTextBox();
    }
}

// 具体工厂(Mac风格组件工厂)
class MacUIFactory implements UIComponentFactory {
    public createButton(): Button {
        return new MacButton();
    }

    public createTextBox(): TextBox {
        return new MacTextBox();
    }
}

// 客户端代码
function renderUI(factory: UIComponentFactory): void {
    const button = factory.createButton();
    const textBox = factory.createTextBox();
    
    button.render();
    textBox.render();
}

// 使用Windows工厂
renderUI(new WindowsUIFactory()); 
// 输出: 渲染Windows风格的按钮
// 输出: 渲染Windows风格的文本框

// 使用Mac工厂
renderUI(new MacUIFactory()); 
// 输出: 渲染Mac风格的按钮
// 输出: 渲染Mac风格的文本框

要点:抽象工厂模式处理创建一系列相关的产品对象,比如按钮和文本框。它确保这些产品在风格或其他特性上相互兼容。

主要区别

  1. 目的

    • 工厂方法模式的重点是创建一个产品,是解决单一产品创建的问题。
    • 抽象工厂模式则是创建一组相关的产品,强调产品之间的关联性。
  2. 复杂性

    • 工厂方法模式相对简单,只需要为每个产品创建一个具体的工厂。
    • 抽象工厂模式相对复杂,需要同时创建多个产品的工厂。
  3. 抽象级别

    • 工厂方法模式通常只定义单一产品的创建。
    • 抽象工厂模式定义的是产品族,即多个相关的产品(如按钮和文本框)共同组成一个完整的产品系列。

总结

尽管工厂方法模式和抽象工厂模式都用于创建对象,但它们的应用场景不同:

  • 工厂方法模式:用于创建单个对象的场景,通常是当产品类型有多个变体但客户端只需要一个产品时。
  • 抽象工厂模式:用于创建多个相关对象的场景,特别是当这些对象属于一个产品族,且必须兼容时。

因此,尽管两者看起来相似,但它们的适用性和复杂性不同。

设计模式-创建型总结

创建型设计模式的核心在于解决对象创建过程中的复杂性和灵活性。通过将对象创建与业务逻辑分离,这些模式提升了代码的扩展性和维护性,遵循了单一职责和开闭原则。它们提供了灵活的对象创建方式,比如工厂方法、抽象工厂、原型和建造者模式,帮助我们在面对不同需求时,选择最合适的对象生成方式。

这些模式使代码更易扩展、维护,并通过面向接口编程减少耦合度。最终,创建型模式不仅提高了代码复用性,还让系统在面对变化时更加灵活、稳健。

使用设计模式虽然在初期会增加代码的复杂性,但它带来了更好的可维护性和扩展性。通过解耦代码,设计模式让系统在面对变化时更加灵活,只需修改局部代码,而不影响整体架构。此外,它减少了类与类之间的依赖,使代码更加模块化和可读,尤其在大型项目中,设计模式有助于应对未来的扩展需求,提升代码质量,降低长期维护的成本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值