Java设计模式之工厂模式

本文详细介绍了Java中的三种工厂模式:简单工厂模式、工厂方法模式和抽象工厂模式,通过制造咖啡的例子阐述了每种模式的特点、应用场景以及优缺点。简单工厂模式扩展性差,适用于快速实现;工厂方法模式通过接口实现产品创建,提高了扩展性;抽象工厂模式则针对多个产品等级结构,提供了一组相关产品的创建,但在产品族扩展时较为复杂。

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

工厂模式有三种:简单工厂模式、工厂方法模式、抽象工厂模式。

这里以制造coffee的例子开始工厂模式设计之旅。我们知道coffee只是一种泛举,在点购咖啡时需要指定具体的咖啡种类:美式咖啡、卡布奇诺、拿铁等等。

接口获取coffee

public abstract class Coffee {
    public abstract String getName();
}

不同咖啡的创建

// 美式咖啡
public class Americano extends Coffee {

    @Override
    public String getName() {
        return "美式咖啡";
    }

}


//卡布奇诺
public class Cappuccino extends Coffee {

    @Override
    public String getName() {
        return "卡布奇诺";
    }

}


// 拿铁
public class Latte extends Coffee {

    @Override
    public String getName() {
        return "拿铁";
    }

}

一、简单工厂模式


public class SimpleFactory {
    
    /**
     * 通过类型获取Coffee实例对象
     */
    public static Coffee createInstance(String type){
        if("americano".equals(type)){
            return new Americano();
        }else if("cappuccino".equals(type)){
            return new Cappuccino();
        }else if("latte".equals(type)){
            return new Latte();
        }else{
            throw new RuntimeException("type["+type+"]类型不可识别,没有匹配到可实例化的对象!");
        }
    }
    
    public static void main(String[] args) {
        Coffee latte = SimpleFactory.createInstance("latte");
        System.out.println("创建的咖啡实例为:" + latte.getName());
    }

}

特点
1、它是一个具体的类,非接口抽象类。有一个重要的create()方法,利用 if 或者 switch 创建产品并返回。create()方法通常是静态的,所以也称之为静态工厂。
2、扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)。

二、工厂方法模式

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类。

场景延伸:不同地区咖啡工厂受制于环境、原料等因素的影响,制造出的咖啡种类有限。中国咖啡工厂仅能制造卡布奇诺、拿铁,而美国咖啡工厂仅能制造美式咖啡、拿铁。

定义一个抽象的咖啡工厂

public abstract class CoffeeFactory {
    
    /**
     * 生产可制造的咖啡
     * @return
     */
    public abstract Coffee[] createCoffee();

}

子类实现工厂方法

子类实现工厂方法
/**
 * 中国咖啡工厂,制造卡布奇诺和拿铁
 */
public class ChinaCoffeeFactory extends CoffeeFactory {

    @Override
    public Coffee[] createCoffee() {
        return new Coffee[]{new Cappuccino(), new Latte()};
    }

}


/**
 * 美国咖啡工厂,制造美式咖啡和拿铁
 */
public class AmericaCoffeeFactory extends CoffeeFactory {

    @Override
    public Coffee[] createCoffee() {
        return new Coffee[]{new Americano(), new Latte()};
    }

}

测试类

public class FactoryMethodTest {

    private static void print(Coffee[] c){
        for (Coffee coffee : c) {
            System.out.println(coffee.getName());
        }
    }
    
    public static void main(String[] args) {
        CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();
        Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();
        System.out.println("中国咖啡工厂可以生产的咖啡有:");
        print(chinaCoffees);
        CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
        Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();
        System.out.println("美国咖啡工厂可以生产的咖啡有:");
        print(americaCoffees);
    }
}

输出:
中国咖啡工厂可以生产的咖啡有:
卡布奇诺
拿铁
美国咖啡工厂可以生产的咖啡有:
美式咖啡
拿铁

特点
1、相比简单工厂方法,增加了一个抽象类(或者接口),由不同的产品工厂去实现该接口;
1、可以一定程度增加扩展性,若增加一个产品实现,只需要实现产品接口,修改工厂创建产品的方法,消费者可以无感知(若消费者不关心具体产品是什么的情况);
2、可以一定程度增加代码的封装性、可读性。清楚的代码结构,对于消费者来说很少的代码量就可以完成很多工作;

适用场景
1、消费者不关心它所要创建对象的类(产品类)的时候。
2、消费者知道它所要创建对象的类(产品类),但不关心如何创建的时候。

三、抽象工厂模式

提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料。如果用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造工厂、碳酸饮料制造工厂),4个具体工厂实现。随着产品的增多,会导致类爆炸。所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担创建者的责任,负责制造不同的产品。

抽象的饮料产品家族制造工厂

public interface AbstractDrinksFactory {

    /**
     * 制造咖啡
     */
    Coffee createCoffee();
    
    /**
     * 制造茶
     */
    Tea createTea();
    
    /**
     * 制造碳酸饮料
     */
    Sodas createSodas();
}

中国饮品工厂,制造咖啡与茶

public class ChinaDrinksFactory implements AbstractDrinksFactory {

    @Override
    public Coffee createCoffee() {
        return new Latte();
    }

    @Override
    public Tea createTea() {
        return new MilkTea();
    }

    @Override
    public Sodas createSodas() {
        return null;
    }

}

美国饮品制造工厂,制造咖啡和碳酸饮料

public class AmericaDrinksFactory implements AbstractDrinksFactory {

    @Override
    public Coffee createCoffee() {
        return new Latte();
    }

    @Override
    public Tea createTea() {
        return null;
    }

    @Override
    public Sodas createSodas() {
        return new CocaCola();
    }

}

抽象工厂模式与工厂方法模式的区别:
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

抽象工厂模式的优点:
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

抽象工厂模式的缺点:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

适用场景:
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。

四、总结

1、简单工厂:不能算是真正意义上的设计模式,但可以将客户程序从具体类解耦,简单方便易上手;

2、工厂方法:使用继承,把对象的创建委托给子类,由子类来实现创建方法,可以看作是抽象工厂模式中只有单一产品的情况;

3、抽象工厂:使对象的创建被实现在工厂接口所暴露出来的方法中;

4、无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
 

参考:https://www.cnblogs.com/carryjack/p/7709861.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值