Java 工厂设计模式详解

Handsome
2025-04-02
点 赞
1
热 度
34
评 论
0

前言

工厂设计模式(Factory Pattern)是最常用的设计模式之一,属于创建型模式。其核心思想是通过引入一个工厂类来实例化对象,而不是直接在客户端代码中使用 new 关键字来创建对象。这种方式能够将对象的创建过程封装起来,使得代码更加灵活、可扩展、易于维护。

工厂模式主要适用于以下场景:

  • 当一个类不知道它所需要的对象的确切类型时。

  • 当一个类希望将创建对象的任务委托给子类时。

  • 当类的创建过程比较复杂时。

工厂模式的种类

工厂设计模式包括以下几种类型,每种模式的适用场景略有不同:

  1. 简单工厂模式:通过一个工厂类来决定创建哪种类型的产品对象。

  2. 工厂方法模式:由子类来决定实例化哪个具体产品。

  3. 抽象工厂模式:提供一个接口用于创建一系列相关产品,而无需指定它们的具体类。

1. 简单工厂模式

1.1 模式概述

简单工厂模式是最基础的工厂模式,其核心思想是通过一个工厂类来决定创建哪种类型的产品对象。客户端并不直接实例化产品类,而是通过工厂类来获得实例。

1.2 类图

简单工厂模式的时序图如下所示:

884a0b40-9329-4000-926e-0223aff041dc.webp

下面我们围绕这个时序图来讲解

1.3 代码示例

假设我们有两种类型的产品,ConcreteProductAConcreteProductB,我们需要根据客户端的需求动态创建相应的产品对象。

// 产品接口
public interface Product {
    void operation(); //具体实现
}

// 具体产品A
public class ConcreteProductA implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductA operation"); //对产品A不同的实现
    }
}

// 具体产品B
public class ConcreteProductB implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductB operation");//对产品B不同的实现
    }
}

// 简单工厂类
public class SimpleFactory {
/**
 * 根据不同的type执行我们不同的产品类型
 */
    public static Product createProduct(String type) {
        if ("productA".equalsIgnoreCase(type)) {
            return new ConcreteProductA();
        } else if ("productB".equalsIgnoreCase(type)) {
            return new ConcreteProductB();
        } else {
            throw new IllegalArgumentException("Unknown product type");
        }
    }
}

// 调用代码
public class Client {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.operation(); // 输出:ConcreteProductA operation

        Product productB = SimpleFactory.createProduct("B");
        productB.operation(); // 输出:ConcreteProductB operation
    }
}
//定义枚举方便维护
public enum ProductType{
    productA,
    productB //枚举中定义产品类型
}

1.4 优缺点

优点

  • 封装性好:客户端代码不需要直接创建产品对象,工厂类负责创建产品实例,客户端只需要知道如何获取产品即可。

  • 降低耦合度:客户端和产品类之间的依赖关系被削弱,工厂类充当了中介角色。

缺点

  • 扩展困难:如果产品种类较多,工厂类的代码会变得非常复杂,因为每增加一种产品,工厂类就需要增加一条判断逻辑,违背了开闭原则。

  • 违反单一职责原则:工厂类负责多个产品的实例化,增加了职责。

a45133b9-7567-4383-b1e7-bc0efaa0af16.jpeg

2. 工厂方法模式

2.1 模式概述

工厂方法模式通过定义一个创建对象的接口,但由子类来决定实例化哪个类。这种模式通过子类来具体化创建产品的方式,使得创建过程更加灵活。客户端代码不需要依赖具体的类,而是依赖于工厂接口来创建产品。

2.2 类图

工厂方法模式的时序图图如下:

2.3 代码示例

在工厂方法模式中,我们定义一个抽象工厂接口,并在子类中实现具体的产品创建方法。

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

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

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

// 抽象工厂类
public interface Creator {
    Product factoryMethod();
}

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

// 具体工厂B
public class ConcreteCreatorB implements 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.operation(); // 输出:ConcreteProductA operation

        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.factoryMethod();
        productB.operation(); // 输出:ConcreteProductB operation
    }
}

2.4 优缺点

优点

  • 符合开闭原则:新增产品时,客户端只需要使用新的工厂类,而无需修改现有代码。

  • 解耦合:客户端代码只依赖工厂接口,而不需要依赖具体的产品类,降低了系统的耦合度。

缺点

  • 工厂类增多:每增加一个具体产品,都需要创建一个新的工厂类,可能导致系统中的类数量激增,增加系统的复杂度。

3. 抽象工厂模式

3.1 模式概述

抽象工厂模式是工厂模式的一种扩展,它不仅创建单一产品,还可以创建一系列相关的产品对象。抽象工厂提供了一个接口,允许客户端创建一组产品对象,而无需指定它们具体的类。这样可以确保一组产品对象在同一工厂下被创建。

3.2 类图

抽象工厂模式的时序图图如下:

cb4175af-a7c0-453d-9245-e8a5d74ed046.webp

3.3 代码示例

// 产品A接口
public interface ProductA {
    void operationA();
}

// 产品B接口
public interface ProductB {
    void operationB();
}

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

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

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

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

// 抽象工厂
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();
        productA1.operationA(); // 输出:ConcreteProductA1 operationA

        ProductB productB1 = factory1.createProductB();
        productB1.operationB(); // 输出:ConcreteProductB1 operationB

        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        productA2.operationA(); // 输出:ConcreteProductA2 operationA

        ProductB productB2 = factory2.createProductB();
        productB2.operationB(); // 输出:ConcreteProductB2 operationB
    }
}

3.4 优缺点

优点

  • 产品族的创建:可以确保同一产品族的产品一起被创建,避免了单个产品在不同的工厂中不兼容的情况。

  • 符合开闭原则:在添加新产品时,只需要新增相应的具体产品和工厂类,而无需修改现有的代码。

缺点

  • 增加了类的数量:每种产品系列都会引入多个工厂类,导致系统的复杂度增加。

  • 扩展困难:若要增加一个新的产品系列,需要修改抽象工厂的接口,违反了开闭原则。


总结

根据实际需求选择不同的工厂模式,能够提高系统的灵活性、可扩展性和可维护性。不同的工厂模式适用于不同的场景,简单工厂适合少量产品,工厂方法和抽象工厂适合产品种类多且需要灵活扩展的情况。


心若有所向往,何惧道阻且长

Handsome

infp 调停者

站长

具有版权性

请您在转载、复制时注明本文 作者、链接及内容来源信息。 若涉及转载第三方内容,还需一同注明。

具有时效性

目录

欢迎来到Handsome的站点,为您导航全站动态

22 文章数
4 分类数
33 评论数
23标签数

访问统计

51统计Logo