工厂设计模式

文章介绍了抽象工厂模式和工厂方法模式的概念、UML图以及应用场景。抽象工厂模式用于创建相关或相关对象族,通过抽象工厂和具体工厂类实现多态性,适用于产品系列有共性特征的情况。工厂方法模式则定义创建对象的接口,由具体子类决定实例化哪个类,降低了代码耦合,适用于简化创建过程和统一管理对象创建的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 抽象工厂模式

抽象工厂模式的原始定义是:提供了一个用于创建相关或相关对象族的接口,而无须指定其具体类

当我们在创建抽象工厂模式时,最终还是会涉及指定具体的实现类。换句话说,定义只是说了抽象工厂模式应该要朝着分析共性规律的方向走,而具体操作时我们还得仔细分析具体实现类该怎么实现才行

只有找到了正确的抽象产品,才能发挥抽象工厂模式的作用

UML图

抽象工厂模式UML图

从这个 UML 图中,我们能看出抽象工厂模式中其实包含了四个关键角色。

  • 抽象工厂
  • 抽象产品(通用的一类对象或接口)
  • 具体工厂
  • 具体产品(继承通用对象或接口后扩展特有属性)
/**
 * @Description 抽象的家具工厂
 */
public abstract class AbsractFactory {
    abstract Chair createChair();
    abstract Sofa createSofa();
    abstract Table createTable();
}
// 具体的工厂1
public class ChinaFactory extends AbsractFactory {
    @Override
    Chair createChair() {
        return new ChinaChair();
    }
    @Override
    Sofa createSofa() {
        return new ChinaSofa();
    }
    @Override
    Table createTable() {
        return new ChinaTable();
    }
}
// 具体的工厂2
public class USAFactory extends AbsractFactory{
    @Override
    Chair createChair() {
        return new USAChair();
    }
    @Override
    Sofa createSofa() {
        return new USASofa();
    }
    @Override
    Table createTable() {
        return new USATable();
    }
}

在实际的代码实现中,抽象工厂模式体现为定义一个抽象工厂类,多个不同的具体工厂继承这个抽象工厂类后,再各自实现相同的抽象功能,进而实现代码上的多态性

使用抽象工厂模式原因:

  • 对于不同产品系列有比较多共性特征时,可以使用抽象工厂模式,有助于提升组件的复用性
  • 当需要提升代码的扩展性并降低维护成本时,把对象的创建和使用过程分开,能有效地将代码统一到一个级别上
  • 解决跨平台带来的兼容性问题

示例1

/**
 * @Description 抽象工厂类
 */
public interface AbstractFactory {

    Pizza createPizza(String orderType);
}
/**
 * @Description 具体工厂1
 */
public class BJFactory implements AbstractFactory {
    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("抽象工厂模式......");
        if ("cheese".equals(orderType)) {
            return new BJCheesePizza();
        } else if ("pepper".equals(orderType)) {
            return new BJPepperPizza();
        }
        return null;
    }
}

/**
 * @Description 具体工厂2
 */
public class LDFactory implements AbstractFactory{
    @Override
    public Pizza createPizza(String orderType) {
        System.out.println("抽象工厂模式......");
        if ("cheese".equals(orderType)){
            return new LDCheesePizza();
        } else if ("pepper".equals(orderType)){
            return new LDPepperPizza();
        }
        return null;
    }
}
/**
 * @Description 抽象产品
 */
public abstract class Pizza {

    protected String name;

    /**
     * 准备原材料
     */
    public abstract void prepare();

    public void bake() {
        System.out.println(name + " baking.");
    }

    public void cut() {
        System.out.println(name + " cutting.");
    }

    public void box() {
        System.out.println(name + " boxting.");
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * @Description 产品1
 */
public class BJCheesePizza extends Pizza {
 @Override
 public void prepare() {
  setName("北京奶酪披萨");
  System.out.println(" 北京奶酪披萨准备原材料");
 }
}


/**
 * @Description 产品2
 */
public class LDCheesePizza extends Pizza {
 @Override
 public void prepare() {
  setName("伦敦奶酪披萨");
  System.out.println(" 伦敦奶酪披萨准备原材料");
 }
}

/**
 * @Description 产品3
 */
public class BJPepperPizza extends Pizza {
 @Override
 public void prepare() {
  setName("北京胡椒披萨");
  System.out.println(" 北京胡椒披萨准备原材料");
 }
}

/**
 * @Description 产品4
 */
public class LDPepperPizza extends Pizza {
 @Override
 public void prepare() {
  setName("伦敦胡椒披萨");
  System.out.println(" 伦敦胡椒披萨准备原材料");
 }
}
/**
 * @Description 测试代码
 */
public class OrderPizza {

    AbstractFactory factory;

    public OrderPizza(AbstractFactory factory){
        this.factory = factory;
        Pizza pizza = null;
        String orderType;
        do {
            orderType = getType();
            pizza = this.factory.createPizza(orderType);
            if (null == pizza){
                System.out.println("没有这种pizza..");
                break;
            }
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while (true);
    }

    private String getType() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 各类: ");
            return reader.readLine();
        } catch (IOException ex) {
            return "";
        }
    }

    public static void main(String[] args) {
//        new OrderPizza(new BJFactory());
        new OrderPizza(new LDFactory());
    }

}

2. 工厂方法模式

工厂方法模式因为只围绕着一类接口来进行对象的创建与使用,使用场景更简单和单一,在实际的项目中使用频率反而比抽象工厂模式更高

工厂方法模式的原始定义是:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。

工厂方法模式的目的很简单,就是封装对象创建的过程,提升创建对象方法的可复用性

为什么要用工厂方法模式?

  • 为了把对象的创建和使用过程分开,降低代码耦合性
  • 减少重复代码
  • 统一管理创建对象的不同实现逻辑

UML图

工厂方法模式

工厂方法模式包含三个关键角色:

  • 抽象接口(也叫抽象产品)
  • 核心工厂
  • 具体产品(也可以是具体工厂)

核心工厂通常作为父类负责定义创建对象的抽象接口以及使用哪些具体产品,具体产品可以是一个具体的类,也可以是一个具体工厂类,负责生成具体的对象实例。于是,工厂方法模式便将对象的实例化操作延迟到了具体产品子类中去完成。

不同于抽象工厂模式,工厂方法模式侧重于直接对具体产品的实现进行封装和调用,通过统一的接口定义来约束程序的对外行为。换句话说,用户通过使用核心工厂来获得具体实例对象,再通过对象的统一接口来使用对象功能

/**
 * @Description 抽象产品
 */
public interface IProduct {
    void apply();
}
//具体产品实现A
public class Product_A_Impl implements IProduct{
    @Override
    public void apply() {
        System.out.println("use A product now");
    }
}
//具体产品实现B
public class Product_B_Impl implements IProduct{
    @Override
    public void apply() {
        System.out.println("use B product now");
    }
}
/**
 * @Description 核心工厂类
 */
public class ProductFactory {

    public static IProduct getProuct(String name){

        if ("a".equalsIgnoreCase(name)){
            return new ProductA();
        }
        return new ProductB();
    }
}
/**
 * @Description 测试用例
 */
public static void main(String[] args) {
    IProduct iProduct = ProductFactory.getProduct(""); // 核心工厂来获得具体实例对象
    iProduct.apply();
    IProduct iProducta = ProductFactory.getProduct("a"); // 通过对象的统一接口来使用对象功能
    iProducta.apply();
}

在工厂方法模式中,核心的工厂 ProductFactory 类不会负责所有产品的创建,只是负责实现通用逻辑,具体的实例创建工作都是交给具体工厂去做的,同时子类需要实现一个公共的接口来对外提供统一的功能,这使得工厂方法模式可以允许程序在不修改工厂角色的情况下引入新的产品实现

工厂方法模式是围绕着特定的抽象产品(一般是接口)来封装对象的创建过程,客户端只需要通过工厂类来创建对象并使用特定接口的功能

使用场景分析

一般情况下,工厂方法模式有以下几个使用场景。

  • 需要使用很多重复代码创建对象时,比如,DAO 层的数据对象、API 层的 VO 对象等。
  • 创建对象要访问外部信息或资源时,比如,读取数据库字段,获取访问授权 token 信息,配置文件等。
  • 创建需要统一管理生命周期的对象时,比如,会话信息、用户网页浏览轨迹对象等。
  • 创建池化对象时,比如,连接池对象、线程池对象、日志对象等。这些对象的特性是:有限、可重用,使用工厂方法模式可以有效节约资源。
  • 希望隐藏对象的真实类型时,比如,不希望使用者知道对象的真实构造函数参数等
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值