引言
设计模式是软件开发中的一个重要概念,旨在提供通用的解决方案来应对常见的设计问题。设计模式可以分为三大类:创造型模式、结构型模式和行为型模式。在这些模式中,创造型设计模式(Creational Design Patterns)专注于对象的创建,确保系统在面对复杂对象构建时具有更好的灵活性和可维护性。
创造型设计模式的核心思想是将对象的创建逻辑与业务逻辑分离,使系统能够在不影响业务代码的情况下,灵活地修改或扩展对象的创建方式。本文将详细介绍几种常见的创造型设计模式,包括工厂模式、抽象工厂模式、单例模式、建造者模式和原型模式。
一、工厂方法模式(Factory Method Pattern)
1.1 模式简介
工厂方法模式是一种常用的创建型设计模式,它通过定义一个创建对象的接口或抽象类,让子类决定实例化哪一个类。工厂方法模式的关键思想是将对象的实例化操作延迟到子类,从而使得客户端不必依赖于具体类的实现。
1.2 模式结构
工厂方法模式的主要参与者包括:
- 抽象工厂(Creator):声明一个创建对象的抽象方法,通常是
createProduct()
方法。 - 具体工厂(Concrete Creator):实现抽象工厂中的创建方法,负责实例化具体的产品对象。
- 产品(Product):定义产品的接口或抽象类。
- 具体产品(Concrete Product):具体实现产品接口的类。
1.3 代码示例
// 产品接口
public interface Product {
void use();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 工厂接口
public abstract class Creator {
public abstract Product createProduct();
}
// 具体工厂A
public class ConcreteCreatorA extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
public class ConcreteCreatorB extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Creator creatorA = new ConcreteCreatorA();
Product productA = creatorA.createProduct();
productA.use();
Creator creatorB = new ConcreteCreatorB();
Product productB = creatorB.createProduct();
productB.use();
}
}
1.4 优缺点
-
优点:
- 遵循开闭原则,方便扩展产品种类。
- 将具体类的创建延迟到子类,避免了客户端与具体类的耦合。
-
缺点:
- 每增加一种产品类型,都需要增加对应的具体工厂类,可能导致类的数量增加。
1.5 适用场景
- 客户端不需要知道所创建对象的具体类。
- 需要创建一系列相关的产品类,而不希望客户端关心具体的实现细节。
二、抽象工厂模式(Abstract Factory Pattern)
2.1 模式简介
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。抽象工厂模式的核心思想是为产品族提供一个统一的创建接口,使得系统能够使用一系列的产品,而不必关心具体的产品类。
2.2 模式结构
抽象工厂模式主要包括:
- 抽象工厂(Abstract Factory):声明创建一系列产品的方法。
- 具体工厂(Concrete Factory):实现抽象工厂中的创建方法,负责具体产品的实例化。
- 抽象产品(Abstract Product):定义产品的接口或抽象类。
- 具体产品(Concrete Product):实现具体产品的类。
2.3 代码示例
// 抽象产品A
public interface ProductA {
void doSomething();
}
// 抽象产品B
public interface ProductB {
void doSomething();
}
// 具体产品A1
public class ConcreteProductA1 implements ProductA {
@Override
public void doSomething() {
System.out.println("产品A1");
}
}
// 具体产品B1
public class ConcreteProductB1 implements ProductB {
@Override
public void doSomething() {
System.out.println("产品B1");
}
}
// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA = factory1.createProductA();
ProductB productB = factory1.createProductB();
productA.doSomething();
productB.doSomething();
}
}
2.4 优缺点
-
优点:
- 分离了具体类的实现,客户端不需要了解产品的具体类。
- 可以方便地扩展和更改产品族,符合开闭原则。
-
缺点:
- 如果需要增加新的产品族,所有的工厂类都需要修改,系统复杂度增加。
2.5 适用场景
- 需要创建一系列相关或相互依赖的对象。
- 系统不应该依赖产品的具体实现。
三、单例模式(Singleton Pattern)
3.1 模式简介
单例模式确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数,确保外部无法创建新实例,进而在类内部控制实例化过程。
3.2 模式结构
单例模式的主要参与者是:
- 单例类(Singleton):提供静态方法用于获取唯一的实例,并确保构造函数为私有。
3.3 代码示例
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.4 优缺点
-
优点:
- 只会生成一个实例,节省了资源。
- 提供全局访问点,易于控制。
-
缺点:
- 多线程环境下需要加锁处理,可能影响性能。
3.5 适用场景
- 需要确保某个类只有一个实例,如线程池、数据库连接池等。
四、建造者模式(Builder Pattern)
4.1 模式简介
建造者模式通过将对象的构建过程拆分为多个步骤,使得复杂对象的构建可以更加灵活。客户端通过指定每个步骤的实现来构建不同类型的对象。
4.2 模式结构
建造者模式的参与者包括:
- 建造者(Builder):定义构建产品的各个部分。
- 具体建造者(Concrete Builder):实现具体的构建步骤。
- 指挥者(Director):负责控制建造过程。
- 产品(Product):表示复杂对象。
4.3 代码示例
// 产品
public class Product {
private String partA;
private String partB;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
@Override
public String toString() {
return "Product [partA=" + partA + ", partB=" + partB + "]";
}
}
// 抽象建造者
public interface Builder {
void buildPartA();
void buildPartB();
Product getResult();
}
// 具体建造者
public class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("构建 PartA");
}
@Override
public void buildPartB() {
product.setPartB("构建 PartB");
}
@Override
public Product getResult() {
return product;
}
}
// 指挥者
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.build
builder.buildPartB();
return builder.getResult();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
System.out.println(product);
}
}
4.4 优缺点
-
优点:
- 建造者模式将产品的构建过程与其表示相分离,使得相同的构建过程可以创建不同的表示。
- 增加新的具体建造者不需要修改已有代码,符合开闭原则。
-
缺点:
- 可能导致系统变得复杂,特别是当产品具有很多细节的构建步骤时。
4.5 适用场景
- 需要构建复杂对象,而该对象由多个部分组成,各部分的构建过程可能需要不同的实现。
- 希望通过同一个构建过程生成不同的产品表示。
五、原型模式(Prototype Pattern)
5.1 模式简介
原型模式通过复制现有的对象来创建新对象,而不是通过实例化类来创建对象。它的核心思想是通过克隆方法实现对象的快速复制,尤其适用于创建代价较大的对象。
5.2 模式结构
原型模式的主要参与者包括:
- 原型(Prototype):定义一个接口,声明
clone()
方法,用于复制对象。 - 具体原型(Concrete Prototype):实现
clone()
方法,负责具体对象的复制。 - 客户端(Client):通过调用原型对象的
clone()
方法来创建新的对象。
5.3 代码示例
// 原型接口
public interface Prototype {
Prototype clone();
}
// 具体原型
public class ConcretePrototype implements Prototype {
private String field;
public ConcretePrototype(String field) {
this.field = field;
}
@Override
public Prototype clone() {
return new ConcretePrototype(this.field);
}
@Override
public String toString() {
return "ConcretePrototype{" +
"field='" + field + '\'' +
'}';
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcretePrototype prototype1 = new ConcretePrototype("原型对象1");
Prototype clonedPrototype = prototype1.clone();
System.out.println(clonedPrototype);
}
}
5.4 优缺点
-
优点:
- 克隆对象比直接创建对象更高效,特别是对于创建代价较高的对象。
- 可以在运行时动态选择并创建符合要求的对象。
-
缺点:
- 如果对象中的属性含有复杂的嵌套对象,深度克隆的实现会变得复杂。
- 需要对每个类都实现克隆方法,增加了系统复杂性。
5.5 适用场景
- 创建对象的代价较高,或者需要通过复杂过程初始化对象。
- 需要避免使用
new
关键字来直接创建对象。
六、总结
创造型设计模式通过提供一系列优雅的解决方案来简化对象的创建过程,帮助开发者从不同的角度解决复杂对象的构建问题。这些模式不仅减少了代码的重复和耦合,还使得系统在扩展时更加灵活。
模式名称 | 主要作用 | 适用场景 |
---|---|---|
工厂方法模式 | 定义一个用于创建对象的接口,让子类决定实例化哪一个类 | 当需要将对象的创建与业务逻辑分离时使用 |
抽象工厂模式 | 提供一个创建相关或相互依赖对象的接口 | 当需要创建一系列相关对象或产品族时使用 |
单例模式 | 确保一个类只有一个实例,并提供全局访问点 | 当系统中某个类的实例必须唯一时使用,如线程池、数据库连接池 |
建造者模式 | 将复杂对象的构建过程分步进行,使构建过程更加灵活 | 当需要构建复杂对象,且构建过程可能有多种方式时使用 |
原型模式 | 通过复制现有对象来创建新对象 | 当创建对象的代价较高,或希望通过克隆快速创建对象时使用 |
通过合理使用创造型设计模式,开发者可以有效降低系统的耦合性,提高系统的可扩展性和维护性。在实际开发中,根据具体场景选择合适的模式是关键。
希望本文能帮助大家更好地理解和运用创造型设计模式,提高代码的设计能力和软件的质量。