天天看点

【利用AI让知识体系化】5种创建型模式

作者:阿珊和她的猫
【利用AI让知识体系化】5种创建型模式

创建型模式

简介

创建型模式,顾名思义,是用来创建对象的模式。在软件开发中,对象的创建往往比一般的编程任务更为复杂,可能涉及到一些琐碎、复杂的过程,例如对象内部的依赖关系确定、对象的实例化方式等。创建型模式的主要功能是将对象的创建过程封装起来,从而隐藏其复杂性,并且可以为客户端提供一种灵活的创建对象的方式。

常见的创建型模式包括:

  1. 工厂模式(Factory Pattern)
  2. 抽象工厂模式(Abstract Factory Pattern)
  3. 单例模式(Singleton Pattern)
  4. 建造者模式(Builder Pattern)
  5. 原型模式(Prototype Pattern)

这些模式可以被分为两类:类创建型模式和对象创建型模式。类创建型模式通过一个类来创建对象实例,而对象创建型模式则通过一个对象来创建新的对象实例。同时,许多创建型模式都执行一些形式的延迟初始化,我们称之为“惰性初始化”,也是许多模式关注的问题之一。

总之,创建型模式主要解决了对象创建过程中的复杂性和灵活性问题,提高了代码的可复用性和可读性。在软件开发中,根据不同的场景和需求选择合适的创建型模式可以帮助开发者更好地完成对象的创建工作。

工厂模式

工厂模式是一种创建型设计模式,它定义了一个用于创建对象的接口,让子类来决定将哪一个类实例化。工厂模式使得创建对象变得更加灵活和可扩展,它将创建具体对象的责任转移给了子类,而不是在客户端代码中直接实例化对象。

工厂模式常用于以下场合:
  1. 对象创建需要复杂的逻辑
  2. 对象的创建涉及到大量的重复代码
  3. 使用工厂模式可以封装类的实例化过程

工厂模式的核心是一个抽象工厂(Factory)类,该类定义了一个创建对象的抽象方法,子类可以通过实现该抽象方法来创建具体的对象。具体工厂类(Concrete Factory)是工厂模式的重要组成部分,主要负责实现抽象工厂类中定义的抽象方法,以便生产出具体的产品。

有两种基本的工厂模式:简单工厂模式和工厂方法模式。简单工厂模式只是用来创建单一类型的对象,而工厂方法模式则可以用来创建一组相关的对象。同时还有一个抽象工厂模式,它用于创建多个产品系列以及产品之间的关联,属于更高层次的模式。

总之,工厂模式可以帮助客户端代码解耦,将对象的实例化过程封装在工厂类中,让程序更加灵活和可扩展。它是一种非常常见的设计模式,被广泛应用于软件开发的各个领域。

这是一个使用 JavaScript 实现的工厂模式的简单示例:
class Product {
  constructor(name) {
    this.name = name;
  }
}

class ProductA extends Product {
  constructor() {
    super("ProductA");
  }
}

class ProductB extends Product {
  constructor() {
    super("ProductB");
  }
}

class Creator {
  factoryMethod() {}
}

class CreatorA extends Creator {
  factoryMethod() {
    return new ProductA();
  }
}

class CreatorB extends Creator {
  factoryMethod() {
    return new ProductB();
  }
}
           

抽象工厂模式

抽象工厂模式是一种创建型设计模式,它提供了一种创建一系列相关或者相互依赖对象的接口,而无需指定实现类。简单来说,抽象工厂模式是一种工厂模式的扩展,可以创建一组相关的对象,而不仅仅是一个对象。

抽象工厂模式常用于以下场合:
  1. 当需要创建一系列相关或相互依赖的对象时
  2. 需要提供一个统一的接口,以便客户端通过抽象接口使用多个具体产品中的一种
  3. 由于业务需求的变化,需要支持新的产品系列
抽象工厂模式由抽象工厂、具体工厂、抽象产品和具体产品四个部分组成。
  1. 抽象工厂(Abstract Factory):定义了创建一系列相关或依赖对象的方法。
  2. 具体工厂(Concrete Factory):实现抽象工厂定义的方法,返回一组相关的产品。
  3. 抽象产品(Abstract Product):定义一类产品的接口。
  4. 具体产品(Concrete Product):实现抽象产品的接口,是抽象工厂创建的对象。

抽象工厂模式可以看做是一组工厂方法的组合,它提供了一种更高层次的抽象,能够将多个相关的对象创建放在同一个工厂中,这样可以更好地维护产品之间的兼容性。

总的来说,抽象工厂模式广泛应用于需要创建一组相关或依赖对象的场合,它使得客户端代码与具体产品的实现相分离,提高了程序模块化和可维护性。

这是一个使用 JavaScript 实现的简单的抽象工厂模式的示例:

class AbstractProductA {
  constructor() {
    if (new.target === AbstractProductA) {
      throw new Error("Cannot instantiate abstract class");
    }
  }

  methodA() {}
}

class AbstractProductB {
  constructor() {
    if (new.target === AbstractProductB) {
      throw new Error("Cannot instantiate abstract class");
    }
  }

  methodB() {}
}

class ProductA1 extends AbstractProductA {
  methodA() {
    console.log("Product A1 - Method A");
  }
}

class ProductA2 extends AbstractProductA {
  methodA() {
    console.log("Product A2 - Method A");
  }
}

class ProductB1 extends AbstractProductB {
  methodB() {
    console.log("Product B1 - Method B");
  }
}

class ProductB2 extends AbstractProductB {
  methodB() {
    console.log("Product B2 - Method B");
  }
}

class AbstractFactory {
  createProductA() {}
  createProductB() {}
}

class ConcreteFactory1 extends AbstractFactory {
  createProductA() {
    return new ProductA1();
  }

  createProductB() {
    return new ProductB1();
  }
}

class ConcreteFactory2 extends AbstractFactory {
  createProductA() {
    return new ProductA2();
  }

  createProductB() {
    return new ProductB2();
  }
}
           

在这个示例中,我们定义了两个抽象产品类 AbstractProductA 和 AbstractProductB,以及两个具体的产品类 ProductA1、ProductA2,以及 ProductB1、ProductB2。然后我们定义了一个抽象工厂类 AbstractFactory,并在其中定义了两个抽象方法 createProductA()、createProductB(),分别用于创建 AbstractProductA 和 AbstractProductB 的实例。最后,我们又定义了两个具体的工厂类 ConcreteFactory1 和 ConcreteFactory2,并分别实现了 AbstractFactory 中的抽象方法。在 ConcreteFactory1 中,实现了 createProductA() 返回 ProductA1 的实例,实现了 createProductB() 返回 ProductB1 的实例。在 ConcreteFactory2 中,实现了 createProductA() 返回 ProductA2 的实例,实现了 createProductB() 返回 ProductB2 的实例。

单例模式

单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个访问这个实例的全局点。单例模式在实际开发中经常用于控制资源的使用,例如全局缓存、配置对象、线程池、数据库连接池等。

单例模式保证了系统中一个类只有一个实例,从而避免了多个实例的产生,节省了系统资源,使得代码执行更加高效、可维护和可扩展。同时,单例模式的实现很简单,只需要提供一个静态方法,返回同一个实例即可。

常见的单例模式实现方式有两种:懒汉式单例模式和饿汉式单例模式。

1. 懒汉式单例模式

懒汉式单例模式是指在第一次获取实例时才进行实例化。优点是可以节省系统资源,缺点是会存在线程安全问题,需要加入同步锁来解决。

2. 饿汉式单例模式

饿汉式单例模式是指在程序启动时进行实例化,不管实例是否被使用。优点是不会出现线程安全问题,缺点是可能会浪费资源,因为实例在程序启动时就被创建,可能在之后并没有被使用到。

同时,单例模式的实现也包括线程安全的单例模式(使用双重检查锁等机制确保线程安全)、枚举类型的单例模式等。此外,单例模式也有一些缺点,例如扩展困难、测试困难等,开发者需要根据实际业务场景来灵活运用单例模式。

总之,单例模式是一种非常常用的设计模式,它可以保证系统中某个类只有一个实例,从而提升系统的性能和可维护性。在实际开发中,需要根据具体业务场景来选择单例模式的实现方式,同时需要注意线程安全和可测试性等问题。

这是一个使用 JavaScript 实现的简单的单例模式的示例:
class Singleton {
  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }

    return Singleton.instance;
  }

  someMethod() {
    console.log("Some method of the Singleton");
  }
}
           

在这个示例中,我们定义了一个类 Singleton,并在其构造函数中使用了一个静态变量 instance。当我们创建这个类的实例时,我们先检查它是否已经存在,如果不存在则创建一个新实例并将其存储在静态变量 instance 中,然后返回这个实例。这样,我们就始终只有一个类的实例被创建,并且可以随时访问它的方法。在这里,我们定义了一个方法 someMethod() 作为单例对象的一个例子。

建造者模式

建造者模式是一种创建型设计模式,它将一个复杂对象的构建与它的表示分离,可以让同样的构建过程创建不同的表示。

建造者模式通常适用于以下情况:
  1. 创建复杂对象时,对象的内部构造非常复杂(多个组件、不同的构造顺序等)
  2. 通过不同的组装顺序可以创建出不同的对象表示
  3. 在对象构造过程中需要进行很多控制,例如参数校验、类型判断等

建造者模式的核心是一个建造者(Builder)和一个指挥者(Director)。建造者负责创建产品的各个部分,而指挥者负责调用建造者来创建产品,并且按照一定的组装顺序来完成产品的创建。建造者模式将一个复杂对象的创建过程进行了拆分,使得在某个步骤出现问题时,不需要整个重新开始构建,只需要针对问题的步骤进行调整即可。

建造者模式的实现通常包括以下几个角色:
  1. 抽象建造者(Builder):定义创建产品各个部分的抽象方法
  2. 具体建造者(Concrete Builder):实现抽象建造者定义的方法,并返回组装好的产品实例
  3. 产品(Product):定义由各个部分组成的复杂对象
  4. 指挥者(Director):负责调用具体建造者来创建产品,在指挥者中也可以定义具体的组装顺序。

在建造者模式中,客户端通常只需关心指挥者和具体建造者,不需要知道产品的具体实现细节。通过将对象的创建和表示分离,建造者模式可以更好地控制对象的创建过程,从而创建出更加灵活和适用的产品。

总的来说,建造者模式适用于创建那些结构复杂,内部组合关系较为复杂的对象。它的实现较为复杂,但是可以提高代码的可复用性和可维护性,同时也可以增加代码的可扩展性。

原型模式

原型模式是一种创建型设计模式,它使用原型实例指定要创建对象的类型,然后通过复制这个原型来创建新的对象。在原型模式中,不需要知道任何对象的创建细节,只需知道需要创建的对象类型即可。

原型模式通过克隆复制一个已有对象来创建新的对象,可以大大减少创建对象的时间,并且可以避免由于手动创建对象而引入的错误。原型模式在实际开发中应用广泛,常用于创建那些具有相似属性的对象,例如创建相似的数据库连接对象或线程池中的线程对象等。

原型模式的核心是原型接口(Prototype),该接口定义了一个克隆自身的方法,并通过该方法来创建新的对象。具体的原型类(Concrete Prototype)实现了原型接口,并实现了克隆方法,用于创建自身的副本。

在使用原型模式时,可以将原型对象缓存在内存中,并在需要时克隆出一个全新的副本来使用。克隆分为浅克隆和深克隆两种方式。浅克隆只会克隆原型对象本身,而不会克隆其引用的对象,深克隆则会将原型对象及其引用的对象一并克隆出来。具体采用哪种方式可以根据具体情况进行选择。

总的来说,原型模式通过复制已有对象的行为来创建新的对象,减少了代码的重复工作,提高了代码的复用性和可维护性。但是需要注意的是,原型对象必须是可复制的,否则无法实现原型模式的效果。

这是一个使用 JavaScript 实现的简单的原型模式的示例:
const prototype = {
  name: "",
  getName: function() {
    return this.name;
  },
  setName: function(name) {
    this.name = name;
  },
  clone: function() {
    return Object.create(this);
  }
};

const objA = Object.create(prototype);
objA.setName("Object A");

const objB = objA.clone();
objB.setName("Object B");

console.log(objA.getName()); // Output: "Object A"
console.log(objB.getName()); // Output: "Object B"
           

在这个示例中,我们先创建了一个原型对象 prototype,它包含了属性 name 和方法 getName()、setName() 和 clone()。然后我们创建了一个对象 objA,并使用 Object.create() 方法将其原型设置为 prototype。我们调用 setName() 方法来设置 objA 的名字。接下来,我们通过调用 objA.clone() 来克隆这个对象,并将其赋值给 objB。我们再次通过调用 setName() 来设置 objB 的名字,这一次我们输入的是 “Object B”。最后,我们分别调用 getName() 方法来获取 objA 和 objB 的名字,并将其打印出来。输出结果是 “Object A” 和 “Object B”,验证了原型模式成功工作。

继续阅读