Java 创建型设计模式详解

Java 创建型设计模式详解

在软件开发中,设计模式是解决特定问题的通用解决方案。设计模式并不依赖于编程语言,但它们在Java等面向对象的语言中非常有用。设计模式可以分为三类:创建型模式、结构型模式和行为型模式。本文将深入探讨六种常见的创建型设计模式:简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式和原型模式。


1. 简单工厂模式(Simple Factory Pattern)

概念
简单工厂模式并不是真正意义上的设计模式,而是一种编程习惯。它通过定义一个工厂类,由这个工厂类根据传入的参数决定创建哪种产品对象,从而避免客户端直接依赖具体产品类。

结构
简单工厂模式通常涉及以下角色:

  • 工厂类(Factory Class):负责根据传入参数实例化相应的产品类对象。
  • 产品类(Product Class):简单工厂模式所生产的对象,通常是接口或抽象类的实现。
  • 客户端(Client):调用工厂类创建产品对象。

示例代码

// 产品接口
public interface Product {
    void use();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

// 工厂类
public class SimpleFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.use();

        Product productB = SimpleFactory.createProduct("B");
        productB.use();
    }
}

优点

  • 简单工厂模式将对象创建逻辑集中在一个工厂类中,便于管理。

缺点

  • 工厂类的职责过重,违反了单一职责原则。
  • 增加新产品时,需要修改工厂类,违反了开闭原则。

2. 工厂方法模式(Factory Method Pattern)

概念
工厂方法模式是简单工厂模式的进一步抽象。它定义了一个创建对象的接口,但由子类决定实例化哪一个类。这样使得工厂方法模式可以用于产品种类较多且变动频繁的场合。

结构

  • 抽象工厂类(Creator):定义了一个或多个抽象工厂方法。
  • 具体工厂类(ConcreteCreator):实现抽象工厂方法,创建并返回一个具体产品实例。
  • 抽象产品类(Product):定义产品对象的接口。
  • 具体产品类(ConcreteProduct):实现抽象产品类的具体产品。

示例代码

// 抽象产品
public interface Product {
    void use();
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("Using Product A");
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("Using Product B");
    }
}

// 抽象工厂
public abstract class Creator {
    public abstract Product factoryMethod();
}

// 具体工厂A
public class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体工厂B
public class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        Creator creatorA = new ConcreteCreatorA();
        Product productA = creatorA.factoryMethod();
        productA.use();

        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.factoryMethod();
        productB.use();
    }
}

优点

  • 符合开闭原则,增加新产品时无需修改已有代码。
  • 代码结构清晰,符合面向对象设计的原则。

缺点

  • 增加新的产品时,需要增加新的工厂类,增加了系统的复杂性。

3. 抽象工厂模式(Abstract Factory Pattern)

概念
抽象工厂模式提供了一个接口,用于创建一系列相关或互相依赖的对象,而无需指定它们的具体类。它通常用于创建一组相关产品,如操作系统的不同界面风格。

结构

  • 抽象工厂类(AbstractFactory):声明创建一组相关产品的方法。
  • 具体工厂类(ConcreteFactory):实现抽象工厂的方法,生成一系列具体产品。
  • 抽象产品类(AbstractProduct):定义产品的接口。
  • 具体产品类(ConcreteProduct):实现具体产品。

示例代码

// 抽象产品A
public interface ProductA {
    void use();
}

// 具体产品A1
public class ConcreteProductA1 implements ProductA {
    @Override
    public void use() {
        System.out.println("Using Product A1");
    }
}

// 具体产品A2
public class ConcreteProductA2 implements ProductA {
    @Override
    public void use() {
        System.out.println("Using Product A2");
    }
}

// 抽象产品B
public interface ProductB {
    void operate();
}

// 具体产品B1
public class ConcreteProductB1 implements ProductB {
    @Override
    public void operate() {
        System.out.println("Operating Product B1");
    }
}

// 具体产品B2
public class ConcreteProductB2 implements ProductB {
    @Override
    public void operate() {
        System.out.println("Operating Product B2");
    }
}

// 抽象工厂
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();
    }
}

// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        ProductB productB1 = factory1.createProductB();
        productA1.use();
        productB1.operate();

        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        ProductB productB2 = factory2.createProductB();
        productA2.use();
        productB2.operate();
    }
}

优点

  • 抽象工厂模式确保相关产品族的一致性,不会出现错配问题。
  • 新增产品族时,只需添加新的具体工厂和产品类,符合开闭原则。

缺点

  • 新增产品种类时,所有工厂类都需要修改,违反了开闭原则。
  • 代码复杂度较高,适合产品种类和产品族较多的场景。

4. 单例模式(Singleton Pattern)

概念
单例模式确保一个类只有一个实例,并提供一个全局访问点。它常用于管理全局资源,如日志管理器、数据库连接池等。

结构

  • 私有构造方法:确保外部无法直接创建实例。
  • 静态私有实例:存储唯一的实例。
  • 静态公共方法:提供获取实例的全局访问点。

示例代码

public class Singleton {
    // 静态私有实例
    private static Singleton instance;

    // 私有构造方法
    private Singleton() {}

    // 静态公共方法
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    // 示例方法
    public void doSomething() {
        System.out.println("Singleton Instance is working");
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        Singleton singleton = Singleton.getInstance();
        singleton.doSomething();
    }
}

优点

  • 单例模式可以确保类只有一个实例,节省系统资源。
  • 提供了全局访问点,使得对象的管理更加集中。

缺点

  • 单例模式容易引发并发问题,必须确保线程安全。
  • 单例类的职责过重,容易违反单一职责原则。
  • 单例模式在某些场景下会造成代码的可测试性变差,因为它无法轻易被替换或模拟。

5. 建造者模式(Builder Pattern)

概念
建造者模式用于创建复杂对象的步骤被分离出来,这些步骤可以按照不同的顺序或规则创建一个对象。与工厂模式不同的是,建造者模式更关注于一步步地构建对象的过程,而非直接创建产品。

结构

  • 产品类(Product):需要被构建的复杂对象。
  • 抽象建造者(Builder):定义创建产品各个部分的接口。
  • 具体建造者(ConcreteBuilder):实现创建产品各个部分的具体方法,并最终组合成产品对象。
  • 指挥者(Director):调用具体建造者中的方法一步步创建产品。

示例代码

// 产品类
public class Product {
    private String partA;
    private String partB;
    private String partC;

    // 省略Getter和Setter方法

    @Override
    public String toString() {
        return "Product [PartA=" + partA + ", PartB=" + partB + ", PartC=" + partC + "]";
    }
}

// 抽象建造者
public abstract class Builder {
    protected Product product = new Product();

    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();

    public Product getResult() {
        return product;
    }
}

// 具体建造者
public class ConcreteBuilder extends Builder {
    @Override
    public void buildPartA() {
        product.setPartA("Part A");
    }

    @Override
    public void buildPartB() {
        product.setPartB("Part B");
    }

    @Override
    public void buildPartC() {
        product.setPartC("Part C");
    }
}

// 指挥者
public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        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);
    }
}

优点

  • 建造者模式可以让构造过程更加灵活,特别适用于构造步骤复杂的对象。
  • 通过引入指挥者,客户端可以从构建过程中解耦。
  • 符合开闭原则,可以方便地扩展新的建造者类。

缺点

  • 构造过程较为复杂时,代码量会显著增加。
  • 每种产品都需要对应一个具体建造者类,增加了系统复杂度。

6. 原型模式(Prototype Pattern)

概念
原型模式通过复制现有的对象来生成新的对象,而不是通过实例化类来创建新的对象。这种模式在创建对象的成本很高,或者创建过程复杂的情况下非常有用。

结构

  • 原型接口(Prototype):声明克隆自身的接口。
  • 具体原型类(ConcretePrototype):实现原型接口,并提供克隆自身的功能。
  • 客户端(Client):通过调用原型类的克隆方法来生成新的对象。

示例代码

// 原型接口
public interface Prototype extends Cloneable {
    Prototype clone();
}

// 具体原型类
public class ConcretePrototype implements Prototype {
    private String field;

    public ConcretePrototype(String field) {
        this.field = field;
    }

    @Override
    public Prototype clone() {
        try {
            return (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public String toString() {
        return "ConcretePrototype [field=" + field + "]";
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        ConcretePrototype prototype = new ConcretePrototype("Prototype Field");
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();
        System.out.println(clone);
    }
}

优点

  • 原型模式可以在运行时动态地改变实际生成的产品类型,提供了更大的灵活性。
  • 可以通过浅克隆或深克隆来控制对象复制的细节。
  • 在创建复杂对象时,比直接使用构造函数效率更高。

缺点

  • 原型模式要求类必须实现 Cloneable 接口,且需要处理克隆时可能出现的深浅拷贝问题。
  • 对于包含循环引用的对象,处理克隆会非常复杂。

总结

创建型设计模式在Java开发中起着至关重要的作用。它们通过不同的方式来管理对象的创建过程,从而提高代码的灵活性、可扩展性和可维护性。在实际应用中,选择合适的创建型设计模式,可以显著改善系统的结构和质量。

  • 简单工厂模式 适用于产品种类少且变化不频繁的场合,但不利于扩展。
  • 工厂方法模式 提供了更好的扩展性,适合产品种类较多且变动频繁的场合。
  • 抽象工厂模式 适用于创建相关联的产品族,保证产品的一致性。
  • 单例模式 适用于需要全局唯一实例的场合,如配置管理、日志管理等。
  • 建造者模式 适用于构造过程复杂且需要灵活构造对象的场合。
  • 原型模式 适用于创建成本高或复杂的对象,通过复制现有对象来快速创建新的实例。

通过理解和运用这些设计模式,开发者可以编写出更加健壮、灵活的Java代码,适应不断变化的需求。

你可能感兴趣的:(JavaSE,设计模式,java,设计模式)