Java 工厂设计模式详解

Java 工厂设计模式详解

前言

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

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

当一个类不知道它所需要的对象的确切类型时。当一个类希望将创建对象的任务委托给子类时。当类的创建过程比较复杂时。工厂模式的种类工厂设计模式包括以下几种类型,每种模式的适用场景略有不同:

简单工厂模式:通过一个工厂类来决定创建哪种类型的产品对象。工厂方法模式:由子类来决定实例化哪个具体产品。抽象工厂模式:提供一个接口用于创建一系列相关产品,而无需指定它们的具体类。1. 简单工厂模式1.1 模式概述简单工厂模式是最基础的工厂模式,其核心思想是通过一个工厂类来决定创建哪种类型的产品对象。客户端并不直接实例化产品类,而是通过工厂类来获得实例。

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

884a0b40-9329-4000-926e-0223aff041dc.webp下面我们围绕这个时序图来讲解

1.3 代码示例假设我们有两种类型的产品,ConcreteProductA 和 ConcreteProductB,我们需要根据客户端的需求动态创建相应的产品对象。

代码语言:javascript复制// 产品接口

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

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

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

代码语言:javascript复制// 产品接口

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.webp3.3 代码示例代码语言:javascript复制// 产品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 优缺点优点:

产品族的创建:可以确保同一产品族的产品一起被创建,避免了单个产品在不同的工厂中不兼容的情况。符合开闭原则:在添加新产品时,只需要新增相应的具体产品和工厂类,而无需修改现有的代码。缺点:

增加了类的数量:每种产品系列都会引入多个工厂类,导致系统的复杂度增加。扩展困难:若要增加一个新的产品系列,需要修改抽象工厂的接口,违反了开闭原则。总结根据实际需求选择不同的工厂模式,能够提高系统的灵活性、可扩展性和可维护性。不同的工厂模式适用于不同的场景,简单工厂适合少量产品,工厂方法和抽象工厂适合产品种类多且需要灵活扩展的情况。

相关推荐

qq同步助如何还原之前的数据库
Bet体育365提款流水

qq同步助如何还原之前的数据库

⏱️ 07-16 👁️ 6462
如何在Python中写注释
Bet体育365提款流水

如何在Python中写注释

⏱️ 01-20 👁️ 6104
更改 Beats 麦克风设置
Bet体育365提款流水

更改 Beats 麦克风设置

⏱️ 01-22 👁️ 2964
《数码大冒险》明星数码兽体验报告??雷克斯
Bet体育365提款流水

《数码大冒险》明星数码兽体验报告??雷克斯

⏱️ 07-08 👁️ 1882
情人去哪找?說破嘴也就這6個地方
365bet手机娱乐

情人去哪找?說破嘴也就這6個地方

⏱️ 07-21 👁️ 7199
监狱中真实的生活是什么样的?
365彩票软件app下载

监狱中真实的生活是什么样的?

⏱️ 10-30 👁️ 6906