Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)

简介: Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)

一、核心概念

在软件设计中,工厂模式是一种常见的设计模式,它提供了一种创建对象的最佳方式。通过工厂模式,我们可以将对象的创建逻辑与使用逻辑分离,降低代码的耦合度,提高系统的可扩展性和可维护性。

Java中的工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

工厂模式的优点

  1. 解耦:将对象的创建和使用过程分开,使得客户端代码无需知道具体对象的创建过程,只需通过工厂获取对象即可。
  2. 降低代码重复:多个地方需要使用对象时,只需调用工厂方法即可,避免了代码的重复。
  3. 减少错误:由于对象的创建过程由工厂统一管理,因此可以减少因客户端错误创建对象而导致的错误。

Java中工厂模式主要三种形态

  1. 简单工厂模式(又称静态工厂方法):定义一个类来负责其他类的实例化,被创建的实例通常具有共同的父类或接口。客户端只需要传入相应的参数,即可获得所需的对象,而无需知道其具体类名。但是,当系统需要引入新的产品时,可能需要修改工厂类的代码,这违反了开闭原则。
  2. 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。客户端针对抽象工厂及抽象产品编程,产品的具体工厂和产品由具体工厂子类实现。这样,当系统需要引入新的产品时,只需增加相应的具体工厂和产品类即可,符合开闭原则。
  3. 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。客户端使用一个抽象的工厂接口来创建产品,而具体的工厂类负责生成具体的产品。这样可以将简单工厂模式和工厂方法模式进行整合,使得产品的创建更加灵活和可扩展。

二、简单工厂模式

简单工厂模式是最简单的工厂模式,它通过一个专门的类来负责创建其他类的实例,而不需要明确指定具体将要创建的类。这个专门的类称为“简单工厂类”或“工厂类”。

在Java中,简单工厂模式是一种创建型设计模式,它由一个单独的类(称为工厂类)负责创建其他类的实例,而无需将这些类的实例化逻辑暴露给客户端。

简单工厂模式通常用于创建具有共同父类或接口的对象的场景。

下面是一个简单工厂模式的Java实现示例:

首先,定义一个产品接口或抽象类:

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

然后,实现具体产品类:

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

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

接下来,创建简单工厂类:

// 简单工厂类
public class SimpleFactory {
    // 静态工厂方法,用于创建产品
    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        } else {
            throw new IllegalArgumentException("不支持的产品类型: " + type);
        }
    }
}


最后,客户端代码可以这样使用简单工厂:

public class Client {
    public static void main(String[] args) {
        // 通过简单工厂创建产品A
        Product productA = SimpleFactory.createProduct("A");
        productA.use(); // 输出:使用具体产品A

        // 通过简单工厂创建产品B
        Product productB = SimpleFactory.createProduct("B");
        productB.use(); // 输出:使用具体产品B

        // 尝试创建不存在的产品类型将抛出异常
        // Product productC = SimpleFactory.createProduct("C");
    }
}

SimpleFactory类包含一个静态方法createProduct,它根据传入的类型字符串创建并返回相应的产品实例。客户端代码通过调用这个静态工厂方法来获取产品实例,而无需直接与具体的产品类交互。

优缺点分析

  • 简单工厂模式的优点在于它将对象的创建逻辑集中在一个单独的工厂类中,从而减少了客户端与具体类之间的耦合;
  • 同时简单易懂,易于实现。
  • 然而,它的一个缺点是当需要引入新的产品类型时,可能需要修改工厂类的代码,这违反了开闭原则(即对扩展开放,对修改封闭)
  • 此外,简单工厂模式还可能导致系统结构变得复杂和难以维护。

在实际应用中,如果需要频繁添加新的产品类型,可能会更倾向于使用抽象工厂模式或其他更灵活的工厂模式。

三、工厂方法模式

工厂方法模式是对简单工厂模式的进一步抽象化。它将对象的创建延迟到子类中进行,从而实现了更好的扩展性。在工厂方法模式中,抽象工厂类负责定义创建产品对象的接口,而具体工厂类则负责实现具体的产品创建逻辑。

下面是一个工厂方法模式的Java实现示例:

首先,定义一个产品接口:

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

然后,实现具体产品类:

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

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

接下来,创建抽象工厂类,并定义工厂方法:

// 抽象工厂类
public abstract class Creator {
    // 工厂方法,声明为抽象方法,由子类实现
    public abstract Product factoryMethod();

    // 一个通用的方法,使用工厂方法来创建产品
    public final Product createProduct() {
        Product product = factoryMethod();
        // 这里可以添加一些额外的逻辑,比如初始化产品等
        return product;
    }
}

然后,实现具体的工厂子类:

// 具体工厂子类A,用于创建ConcreteProductA
public class ConcreteCreatorA extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductA();
    }
}

// 具体工厂子类B,用于创建ConcreteProductB
public class ConcreteCreatorB extends Creator {
    @Override
    public Product factoryMethod() {
        return new ConcreteProductB();
    }
}

最后,客户端代码可以这样使用工厂方法模式:

public class Client {
    public static void main(String[] args) {
        // 使用具体工厂子类A来创建产品A
        Creator creatorA = new ConcreteCreatorA();
        Product productA = creatorA.createProduct();
        productA.use(); // 输出:使用具体产品A

        // 使用具体工厂子类B来创建产品B
        Creator creatorB = new ConcreteCreatorB();
        Product productB = creatorB.createProduct();
        productB.use(); // 输出:使用具体产品B
    }
}

例子中,Creator是一个抽象工厂类,它声明了一个抽象方法factoryMethod(),这个方法由具体的工厂子类(ConcreteCreatorA和ConcreteCreatorB)来实现。客户端代码通过创建具体工厂类的实例并调用createProduct()方法来创建产品。每个具体工厂类都知道如何创建和返回一种具体的产品。


优缺点分析

工厂方法模式的优点在于它允许系统在不修改具体工厂类的情况下引进新的产品,这符合开闭原则。

此外,它还提供了一种将产品类与客户端代码解耦的机制,因为客户端代码只依赖于抽象产品和抽象工厂,而不是具体实现。

同时,它也降低了代码的耦合度,提高了系统的可扩展性和可维护性。

但是,与简单工厂模式相比,工厂方法模式需要定义更多的类,增加了系统的复杂度。

四、抽象工厂模式

抽象工厂模式是对工厂方法模式的进一步抽象化。它提供了一组用于创建一系列相关或互相依赖对象的接口,而不需要指定它们具体的类。在抽象工厂模式中,抽象工厂类负责定义创建产品家族的接口,而具体工厂类则负责实现具体的产品家族创建逻辑。产品家族是指位于不同产品等级结构中,功能相关联的产品组成的家族。

以下是Java中实现抽象工厂模式的一种方式:

首先,定义产品接口:

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

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

然后,实现具体产品:

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

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

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

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

接下来,定义抽象工厂接口:

public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

然后,实现具体工厂:

// 具体工厂1,负责创建产品A1和产品B1
public class ConcreteFactory1 implements AbstractFactory {
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

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

// 具体工厂2,负责创建产品A2和产品B2
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) {
        // 使用具体工厂1来创建产品
        AbstractFactory factory1 = new ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        ProductB productB1 = factory1.createProductB();
        productA1.use(); // 输出:使用具体产品A1
        productB1.use(); // 输出:使用具体产品B1

        // 使用具体工厂2来创建产品
        AbstractFactory factory2 = new ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        ProductB productB2 = factory2.createProductB();
        productA2.use(); // 输出:使用具体产品A2
        productB2.use(); // 输出:使用具体产品B2
    }
}

例子中,AbstractFactory接口定义了两个创建产品的方法,createProductA()和createProductB()。ConcreteFactory1和ConcreteFactory2分别实现了这些方法以创建不同的具体产品。客户端代码通过具体的工厂来创建和使用产品,而不需要直接与具体产品类打交道。这种方式提供了更好的灵活性和可扩展性,因为你可以在不修改客户端代码的情况下增加新的工厂和产品。


总结

在实际开发中,抽象工厂模式的实现可能更加复杂和庞大。为了保持代码的清晰和可维护性,我们需要合理地划分产品等级结构和产品家族,并遵循单一职责原则和开闭原则进行设计。同时,在实际应用中,我们可以根据具体需求选择使用简单工厂模式、工厂方法模式或抽象工厂模式中的任意一种或多种组合使用以满足需求。例如,在某些情况下,我们可以将简单工厂模式与工厂方法模式结合使用以简化代码结构并提高灵活性;而在其他情况下,我们可能需要使用抽象工厂模式来处理更复杂的对象创建场景。


相关文章
|
10月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
1112 157
|
10月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
985 2
|
12月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
10月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
2675 35
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
293 0
|
10月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
698 8
|
12月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。