目录
一、简介
二、分类
1、类创建型模式
1.1、工厂方法模式
产品接口和具体产品
工厂接口和具体工厂
2、对象创建型模式
2.1、抽象工厂模式
产品接口和具体产品
抽象工厂接口和具体工厂
客户端
2.2、建造者模式
产品类
建造者接口和具体建造者
客户端
2.3、原型模式
原型接口和具体原型类
客户端
2.4、单例模式
饿汉式单例
懒汉式单例
三、总结
创建型模式,用来创建对象的模式,创建型模式抽象了实例化的过程,帮助一个系统独立于如何创建,组合和表示它的对象。
工厂方法模式提供了一种在创建对象时将对象的实例化延迟到子类的方式。在工厂方法模式中,定义了一个抽象的工厂接口,具体的工厂子类负责创建具体的产品对象。这种模式可以使客户端代码与具体产品的创建过程解耦,使系统更加灵活和可扩展。
// 产品接口
interface Product {
void doSomething();
}
// 具体产品类 A
class ConcreteProductA implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductA does something.");
}
}
// 具体产品类 B
class ConcreteProductB implements Product {
@Override
public void doSomething() {
System.out.println("ConcreteProductB does something.");
}
}
// 工厂接口
interface Factory {
Product createProduct();
}
// 具体工厂类 A
class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂类 B
class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
public class Main {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.doSomething();
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.createProduct();
productB.doSomething();
}
}
以上示例中我们定义了一个产品接口 Product
和两个具体的产品类 ConcreteProductA
和 ConcreteProductB
。然后,我们定义了一个工厂接口 Factory
和两个具体的工厂类 ConcreteFactoryA
和 ConcreteFactoryB
,每个工厂类负责创建不同的产品。客户端代码通过工厂接口来创建产品,实现了对象的创建与使用的分离。
工厂方法模式通过将产品的创建封装在具体的工厂类中,使得系统更加灵活,当需要新增产品时,只需要新增一个具体的产品类和一个对应的具体工厂类即可,不需要修改已有的代码。这样,代码的扩展性和维护性得到了提高。
抽象工厂模式提供了一种在创建一组相关或依赖对象时的方式。与工厂方法模式类似,抽象工厂模式也通过接口来定义创建对象的方法,但不同之处在于,抽象工厂模式中的工厂接口可以创建一系列的产品,而不仅仅是单一的产品。
// 产品接口 A
interface ProductA {
void doSomething();
}
// 具体产品类 A1
class ConcreteProductA1 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA1 does something.");
}
}
// 具体产品类 A2
class ConcreteProductA2 implements ProductA {
@Override
public void doSomething() {
System.out.println("ConcreteProductA2 does something.");
}
}
// 产品接口 B
interface ProductB {
void doSomething();
}
// 具体产品类 B1
class ConcreteProductB1 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB1 does something.");
}
}
// 具体产品类 B2
class ConcreteProductB2 implements ProductB {
@Override
public void doSomething() {
System.out.println("ConcreteProductB2 does something.");
}
}
// 抽象工厂接口
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂类 1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂类 2
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
public class Main {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.doSomething();
productB1.doSomething();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.doSomething();
productB2.doSomething();
}
}
接口 ProductA
和 ProductB
,以及对应的具体产品类。然后,我们定义了抽象工厂接口 AbstractFactory
和两个具体的工厂类 ConcreteFactory1
和 ConcreteFactory2
,每个工厂类负责创建一系列相关的产品。客户端代码通过抽象工厂接口来创建产品,实现了对象的创建与使用的分离。
抽象工厂模式适用于需要一次性创建一组相关对象的场景,例如不同风格的UI组件、不同数据库的访问方式等。这种模式可以确保一组产品对象之间的一致性,同时也能够灵活地扩展和切换不同系列的产品。
建造者模式允许你创建复杂的对象,同时可以隐藏对象的构建过程。通过将对象的构建步骤分解到不同的方法中,建造者模式可以使得客户端代码与实际构建过程解耦,从而可以灵活地组合不同的构建步骤,创建出不同的对象配置。
class Computer {
private String cpu;
private String gpu;
private int ram;
private int storage;
public void setCpu(String cpu) {
this.cpu = cpu;
}
public void setGpu(String gpu) {
this.gpu = gpu;
}
public void setRam(int ram) {
this.ram = ram;
}
public void setStorage(int storage) {
this.storage = storage;
}
@Override
public String toString() {
return "Computer [cpu=" + cpu + ", gpu=" + gpu + ", ram=" + ram + "GB, storage=" + storage + "GB]";
}
}
interface Builder {
void buildCPU(String cpu);
void buildGPU(String gpu);
void buildRAM(int ram);
void buildStorage(int storage);
Computer getResult();
}
class ConcreteBuilder implements Builder {
private Computer computer = new Computer();
@Override
public void buildCPU(String cpu) {
computer.setCpu(cpu);
}
@Override
public void buildGPU(String gpu) {
computer.setGpu(gpu);
}
@Override
public void buildRAM(int ram) {
computer.setRam(ram);
}
@Override
public void buildStorage(int storage) {
computer.setStorage(storage);
}
@Override
public Computer getResult() {
return computer;
}
}
public class Main {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
builder.buildCPU("Intel i7");
builder.buildGPU("NVIDIA RTX 3080");
builder.buildRAM(16);
builder.buildStorage(1000);
Computer computer = builder.getResult();
System.out.println("Assembled computer: " + computer);
}
}
建造者模式适用于需要创建具有复杂配置的对象,或者创建过程涉及多个步骤、需要按照不同的顺序组合步骤的场景。通过建造者模式,可以将复杂对象的创建过程与客户端解耦,使得代码更加可维护和扩展。
原型模式允许通过复制现有对象来创建新的对象,而无需知道对象的具体实现细节。原型模式在创建对象时避免了复杂的构造过程,特别适用于那些实例化过程非常昂贵的类。‘
interface Prototype {
Prototype clone();
}
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 Main {
public static void main(String[] args) {
Prototype original = new ConcretePrototype("Original Object");
System.out.println("Original: " + original);
Prototype clone = original.clone();
System.out.println("Clone: " + clone);
}
}
原型模式适用于创建成本较高的对象,或者需要动态生成对象的情况。通过原型模式,可以减少对象的实例化次数,提高系统的性能和效率。
单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于需要全局唯一性的资源,例如配置管理、数据库连接池等。
在饿汉式单例中,实例在类加载时就已经创建好,保证了在多线程环境下的安全性。
class SingletonEager {
private static final SingletonEager instance = new SingletonEager();
private SingletonEager() {
// 私有构造方法
}
public static SingletonEager getInstance() {
return instance;
}
}
懒汉式单例在首次调用 getInstance
方法时创建实例,可以实现延迟加载,但需要注意线程安全问题。
class SingletonLazy {
private static volatile SingletonLazy instance;
private SingletonLazy() {
// 私有构造方法
}
public static SingletonLazy getInstance() {
if (instance == null) {
synchronized (SingletonLazy.class) {
if (instance == null) {
instance = new SingletonLazy();
}
}
}
return instance;
}
}
单例模式适用于需要全局唯一性实例的场景,可以避免资源浪费和状态不一致的问题。但需要注意在多线程环境下的线程安全性问题,可以通过加锁等方式来解决。
创建型模式是一组设计模式,关注于对象的实例化过程,提供了灵活、可复用的方法来创建对象,同时隐藏了创建对象的细节。这些模式帮助我们解决了对象创建过程中的复杂性、灵活性和扩展性等问题。在创建型模式中,共有五种主要的模式:
工厂方法模式(Factory Method Pattern): 定义一个创建对象的接口,但将具体对象的实例化交给子类来完成。这样可以将对象的创建与使用分离,使得系统更加灵活。
抽象工厂模式(Abstract Factory Pattern): 提供一个接口,用于创建一系列相关或依赖的对象,而无需指定具体的类。通过切换不同的具体工厂,可以创建不同系列的产品。
建造者模式(Builder Pattern): 将一个复杂对象的构建过程分解成一系列的步骤,允许客户端代码按需组合和配置这些步骤,从而创建出不同配置的对象。
原型模式(Prototype Pattern): 通过复制现有对象来创建新对象,避免了复杂的构造过程。通过克隆可以创建一个与原对象相同的新对象,但是对象之间是独立的。
单例模式(Singleton Pattern): 确保一个类只有一个实例,并提供一个全局访问点。单例模式适用于需要全局唯一性实例的场景,例如配置管理、数据库连接池等。
这些创建型模式都旨在降低对象创建的复杂性、提供更好的控制和封装、提供更灵活的创建和配置选项,并在适当的情况下优化性能。选择适合场景的创建型模式可以使得代码更加模块化、易于维护和扩展。