设计模式之工厂方法模式与抽象工厂模式

本文通过造汽车的例子详细介绍了简单工厂模式、工厂方法模式及抽象工厂模式。对比了三种模式的优劣,并通过代码示例展示了如何根据需求灵活选择合适的工厂模式。

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

设计模式之工厂方法模式与抽象工厂模式

工厂方法模式(Factory Method): 定义一个用于创建对象的接口,让子类决定去将哪一个类实例化。Factory Method是一个类的实例化延迟到其子类

简单地说:工厂模式就是依据需求生产不同的对象供我们使用的。


需求:造汽车。生产出不同类型的汽车如宝马、奔驰等


简单工厂模式

在说工厂模式之前,不得不提简单工单模式。首先我们依据简单工厂模式实现我们的需求。

汽车父类Car:

public class Car {

    protected String carBrand() {

        return null;
    }

    private String production() {
        return "汽车开始生产啦~ ";
    }

    private String assemble() {

        return "汽车开始组装啦~ ";
    }

    public void run() {

        System.out.println(carBrand()+ production()+ assemble()+"汽车跑起来啦~");
    }
}

奔驰:

public class Benz extends Car {
    @Override
    protected String carBrand() {
        return "奔驰";
    }
}

宝马:

public class Bmw extends Car {

    @Override
    protected String carBrand() {
        return "宝马";
    }
}

代码和例子都非常简单,不需要解释。

对外提供简单工厂方法:

public class CarSimpleFactory {
    /**
     * 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断。根据条件去决定实例化的类。
     * 对于客户端来说,去除了具体产品的依赖。
     * 如果需要增加新的类的话,需要修改原来的代码。
     */
    public static Car creatCar(String type) {
        Car car = null;
        switch (type) {
            case "Benz":
                car = new Benz();
                break;

            case "Bmw":
                car = new Bmw();
                break;
            default:
                break;
        }

        return car;
    }
}

运行:

public class test {

    public static void main(String[] args) {
        //简单工厂
        Car benz = CarSimpleFactory.creatCar("Benz");
        benz.run();
        Car bmw = CarSimpleFactory.creatCar("Bmw");
        bmw.run();

        // 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
        // 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
    }
}

可以看到,如果我们需要一辆奔驰,我们在制造该对象时需要传入相应的条件。如果我们现在需要新增一辆法拉利汽车的话,我们则需要直接对CarSimpleFactory 类进行修改,这违反了开-闭原则。
那么,接下来看一下工厂方法模式针对这一缺点是如何改进的呢?


CarSimpleFactory 改为ICarFactory接口:

public interface ICarFactory {

    //工厂方法的逻辑判断移到了客户端,客户端需要决定去实例化哪一个类。逻辑选择判断的问题依旧存在。从工厂类转移到了客户端。
    Car creatCar();
}

汽车父类:

public abstract class Car implements ICarFactory{

    abstract String carBrand();

    private String production() {
        return "汽车开始生产啦~ ";
    }

    private String assemble() {
        return "汽车开始组装啦~ ";
    }

    public void run() {
        System.out.println(carBrand() + production() + assemble() + "汽车跑起来啦~");
    }
}

奔驰,子类返回一个自身对象:

public class Benz extends Car{
    @Override
    public Car creatCar() {
        return new Benz();
    }

    @Override
    String carBrand() {
        return "奔驰";
    }
}

运行:


public class test {

    public static void main(String[] args) {
        //简单工厂
        Car benz = CarSimpleFactory.creatCar("Benz");
        benz.run();
        Car bmw = CarSimpleFactory.creatCar("Bmw");
        bmw.run();

        //工厂方法
        ICarFactory benz2 = new Benz();
        benz2.creatCar().run();
        ICarFactory bmw2 = new Bmw();
        bmw2.creatCar().run();
        // 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
        // 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
    }
}

可以看到:如果我们现在需要增加一辆法拉利的话,不需要对原来的代码进行修改,而是写一个法拉利子类实现ICarFactory工厂。在我们需要时,直接new一个法拉利出来就行了。


抽象工厂模式(Abstract Factory): 提供一个创建一系列相关或依赖对象的接口,而无需指定它们具体的类。


这里我选择使用配置文件加反射进行解耦。

创建一个factory.properties,指定我们需要创建的对象的类型。

carType=Benz

这个时候我们的工厂类carFactory:

public class CarFactory {

    private static String carType;

    private static String className = "Creational.AbstractFactory.";

    private static Properties pp = new Properties();

    static {

        try {
            pp.load(CarFactory.class.getResourceAsStream("factory.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 这个时候我们需要创建不同的汽车对象时只需要修改配置文件即可。
     *
     * @return
     */
    public static Car creatCar() {
        Car car = null;

        carType = pp.getProperty("carType");

        try {
            Class clazz = Class.forName(className + carType);

            car = (Car) clazz.getConstructor().newInstance();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return car;
    }

}

运行:

public class test {

    public static void main(String[] args) {
        //简单工厂
//        Car benz = CarSimpleFactory.creatCar("Benz");
//        benz.run();
//        Car bmw = CarSimpleFactory.creatCar("Bmw");
//        bmw.run();
//
//        //工厂方法
//        ICarFactory benz2 = new Benz();
//        benz2.creatCar().run();
//        ICarFactory bmw2 = new Bmw();
//        bmw2.creatCar().run();
        // 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
        // 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~

        //抽象工厂
        //根据配置文件获取类信息,进行反射创建出对象
        CarFactory.creatCar().run();
        // 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
    }
}

如果我们想创建一个宝马汽车对象,我们只需要把配置文件修改为:

carType=Bmw

这时候就不需要对源代码进行任何的修改了。

源码地址

本文地址:http://blog.youkuaiyun.com/prodigalwang/article/details/76030272

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值