创建型设计模式关注的是对象的创建过程,旨在将对象的创建与使用分离,从而提高程序的灵活性和可复用性。以下是几种常见的创建型设计模式:
每种创建型模式都有其特定的应用场景和优势,选择合适的模式取决于具体的需求和上下文环境。理解这些模式可以帮助开发者编写更加灵活、易于维护的代码。此外,合理地应用设计模式能够提高代码的可读性和可扩展性,同时也促进了代码的重用。
工厂方法模式(Factory Method Pattern)和抽象工厂模式(Abstract Factory Pattern)都是创建型设计模式,用于将对象的创建与使用分离,从而提高代码的灵活性和可维护性。然而,它们的应用场景和结构有所不同。
工厂方法模式定义了一个创建对象的接口,但由子类决定实例化哪一个类。这种模式让一个类的实例化延迟到其子类。它提供了一种在不修改现有代码的情况下引入新类型的机制,符合开闭原则(对扩展开放,对修改关闭)。
假设你有一个Document
接口和两个具体实现:PDFDocument
和TextDocument
。你可以定义一个DocumentCreator
类,其中包含一个工厂方法createDocument()
,该方法返回Document
类型的对象。然后,你可以创建两个子类PDFCreator
和TextCreator
,分别重写createDocument()
以返回相应的文档类型。
抽象工厂模式提供了一组相关或相互依赖的对象的创建接口,而无需指定它们具体的类。这个模式通常用来创建一系列相关的对象,这些对象属于同一个家族,但是每个家族都有不同的变体。
继续上面的例子,现在我们不仅有Document
,还有Printer
。对于每个Document
类型(如PDFDocument
和TextDocument
),我们也有对应的Printer
类型(如PDFPrinter
和TextPrinter
)。我们可以定义一个DocumentFactory
接口,它有两个方法:createDocument()
和createPrinter()
。然后为每个产品族创建一个具体的工厂类,例如PDFFactory
和TextFactory
,它们实现了DocumentFactory
接口并提供相应的产品组合。
这两种模式都可以帮助开发者解耦对象的创建过程和使用过程,从而使代码更加灵活、易于维护和扩展。
建造者模式是一种创建型设计模式,它允许逐步构建复杂的对象。建造者模式通常用于以下场景:当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;或者当构造过程必须允许被构造的对象有不同的表示时。
下面是一个简单的Java示例,展示了如何使用建造者模式来构建一个复杂的对象——在这里我们以构建一辆Car
为例:
// 产品类
class Car {
private String make;
private String model;
private int year;
private String engine;
private String transmission;
// 私有构造函数,防止直接实例化
private Car(Builder builder) {
this.make = builder.make;
this.model = builder.model;
this.year = builder.year;
this.engine = builder.engine;
this.transmission = builder.transmission;
}
// 静态内部类 Builder
public static class Builder {
private String make;
private String model;
private int year;
private String engine;
private String transmission;
// 必填项
public Builder(String make, String model) {
this.make = make;
this.model = model;
}
// 可选项 - 设置年份
public Builder setYear(int year) {
this.year = year;
return this; // 返回当前Builder对象,实现链式调用
}
// 可选项 - 设置引擎
public Builder setEngine(String engine) {
this.engine = engine;
return this;
}
// 可选项 - 设置变速器类型
public Builder setTransmission(String transmission) {
this.transmission = transmission;
return this;
}
// 构建最终的Car对象
public Car build() {
return new Car(this);
}
}
@Override
public String toString() {
return "Car{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
", year=" + year +
", engine='" + engine + '\'' +
", transmission='" + transmission + '\'' +
'}';
}
}
// 测试代码
public class TestBuilderPattern {
public static void main(String[] args) {
Car car = new Car.Builder("Toyota", "Corolla")
.setYear(2023)
.setEngine("1.8L")
.setTransmission("CVT")
.build();
System.out.println(car.toString());
}
}
在这个例子中,Car
类有一个私有的构造函数,这意味着不能直接通过 new
关键字来创建它的实例。相反,我们提供了一个静态内部类 Builder
来帮助构建 Car
对象。Builder
类包含了所有必要的参数和可选参数,并提供了相应的设置方法。每个设置方法都返回 this
引用,使得可以进行链式调用。最后,通过 build()
方法来创建 Car
实例。这样做的好处是,不仅可以让代码更加清晰,而且还可以确保某些属性在创建对象之前已经被正确设置了。
public class Singleton {
// 使用 volatile 关键字确保当 uniqueInstance 变量被初始化成 Singleton 实例时,多个线程能够正确处理 uniqueInstance 变量
private static volatile Singleton uniqueInstance;
// 私有构造函数,防止外界直接创建 Singleton 的实例
private Singleton() {}
// 静态方法,用于获取唯一实例
public static Singleton getInstance() {
if (uniqueInstance == null) { // 第一次检查
synchronized (Singleton.class) {
if (uniqueInstance == null) { // 第二次检查
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
// 定义一个抽象类或接口作为原型
abstract class Prototype implements Cloneable {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 克隆当前对象
public abstract Prototype clone();
}
// 具体的原型类
class ConcretePrototype extends Prototype {
@Override
public Prototype clone() {
try {
// 调用父类的克隆方法
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}
// 测试代码
public class Test {
public static void main(String[] args) {
// 创建原型对象
ConcretePrototype prototype = new ConcretePrototype();
prototype.setName("Prototype1");
// 通过克隆创建新对象
ConcretePrototype copy = (ConcretePrototype) prototype.clone();
System.out.println("Original Name: " + prototype.getName());
System.out.println("Cloned Name: " + copy.getName());
}
}
日常工作中我们都听说过抽象工厂模式、工厂方法模式、简单工厂模式、静态工厂模式。他们名称类型,以至于傻傻分不清楚。其实他们都属于创建型设计模式,用于对象的创建,但它们各自有不同的应用场景和实现方式。下面我将分别介绍这四种模式。
// 抽象产品A
interface ProductA {}
// 具体产品A1
class ConcreteProductA1 implements ProductA {}
// 具体产品A2
class ConcreteProductA2 implements ProductA {}
// 抽象产品B
interface ProductB {}
// 具体产品B1
class ConcreteProductB1 implements ProductB {}
// 具体产品B2
class ConcreteProductB2 implements ProductB {}
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
public ProductA createProductA() { return new ConcreteProductA1(); }
public ProductB createProductB() { return new ConcreteProductB1(); }
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
public ProductA createProductA() { return new ConcreteProductA2(); }
public ProductB createProductB() { return new ConcreteProductB2(); }
}
// 产品接口
interface Product {
void use();
}
// 具体产品
class ConcreteProduct implements Product {
public void use() { /* 使用产品 */ }
}
// 抽象创建者
abstract class Creator {
// 工厂方法
abstract Product factoryMethod();
}
// 具体创建者
class ConcreteCreator extends Creator {
public Product factoryMethod() {
return new ConcreteProduct();
}
}
// 产品接口
interface Product {
void use();
}
// 具体产品1
class ConcreteProduct1 implements Product {
public void use() { /* 使用产品 */ }
}
// 具体产品2
class ConcreteProduct2 implements Product {
public void use() { /* 使用产品 */ }
}
// 简单工厂类
class SimpleFactory {
public static Product createProduct(String type) {
if ("ConcreteProduct1".equals(type)) {
return new ConcreteProduct1();
} else if ("ConcreteProduct2".equals(type)) {
return new ConcreteProduct2();
}
return null;
}
}
// 产品接口
interface Product {
void use();
}
// 具体产品
class ConcreteProduct implements Product {
public void use() { /* 使用产品 */ }
}
// 静态工厂类
class StaticFactory {
public static Product createProduct() {
return new ConcreteProduct();
}
}
每种工厂模式都有其适用场景,选择哪种模式取决于具体的需求和上下文环境。例如,如果你需要创建一系列相关的对象,那么抽象工厂模式可能是最合适的;如果只是想简化对象的创建过程,并且创建逻辑不复杂,可以考虑使用简单工厂或静态工厂模式。工厂方法模式则非常适合那些需要灵活性和扩展性的场合。