JAVA设计模式——工厂方法模式和抽象工厂模式

工厂模式属于设计模式中的创建型模式。其思想是:客户指定需要的对象,把需求告诉工厂,工厂负责创建对象并返回给客户。工厂模式又分为工厂方法模式和静态工厂模式,下面分别来谈谈。

工厂方法模式

工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。

想象这样一个场景:有一个汽车工厂,客户可向工厂提交订单,选择何种底盘和何种引擎,工厂根据订单生产汽车交付给客户。这就是一个工厂方法的模型,如图:
这里写图片描述
代码实现如下:

底盘:

public interface Chassis {
    String identify();
}

public class ChassisBenz implements Chassis {
    @Override
    public String identify() { return "this is a Chassis of Benz."; }
}

public class ChassisBMW implements Chassis {
    @Override
    public String identify() { return "this is a Chassis of BMW."; }
}

引擎:

public interface Engine {
    String identify();
}

public class EngineBenz implements Engine {
    @Override
    public String identify() { return "this is an Engine of Benz."; }
}

public class EngineBMW implements Engine {
    @Override
    public String identify() { return "this is an Engine of BMW."; }
}

底盘工厂:

public class ChassisFactory {
    // 生成底盘的方法,根据传入的类型生产对应类型的底盘
    public static Chassis createChassis(String chassisType) {
        Chassis chassis;
        switch (chassisType) {
            case "Benz": chassis = new ChassisBenz(); break;
            case "BMW": chassis = new ChassisBMW(); break;
            default: chassis = null;
        }
        return chassis;
    }
}

引擎工厂:

public class EngineFactory {
    // 生成引擎的方法,根据传入的类型生产对应类型的引擎
    public static Engine createEngine(String engineType) {
        Engine engine;
        switch (engineType) {
            case "Benz": ngine = new EngineBenz(); break;
            case "BMW": engine = new EngineBMW();  break;
            default: engine = null;
        }
        return engine;
    }
}

汽车工厂:

public class CarFactory {
    private Chassis chassis;
    private Engine engine;

    // 根据指定的底盘和引擎类型生产一部汽车
    public void createCar(String chassisType, String engineType) {
        this.chassis = ChassisFactory.createChassis(chassisType);
        this.engine = EngineFactory.createEngine(engineType);
        System.out.println("A car is created.");
        System.out.printf("CHASSIS: %s\n", chassis.identify());
        System.out.printf("ENGINE: %s", engine.identify());
    }
}

客户:

public class Client {
    // 下一个汽车订单
    public void orderACar(String chassisType, String engineType) {
        CarFactory cf = new CarFactory();
        cf.createCar(chassisType, engineType);
    }
}

// 测试
class ClientTest {
    public static void main(String[] args) {
        Client client = new Client();
        client.orderACar("BMW", "BMW");
    }
}

运行结果:

A car is created.
CHASSIS: this is a Chassis of BMW.
ENGINE: this is an Engine of BMW.

可以看到,客户只需要传入需求,工厂就会根据客户的需求生产产品,客户无需知道具体的实现过程,这使用户与产品实现了一定程度的解耦(但产品与工厂耦合了)。

但问题也是显而易见的。例如用户传入一个BMW的底盘和一个Benz的引擎,工厂并不会理会,而会按照用户的选择,生产出一部古怪的汽车(或是这两个零件无法组合在一起)。在某些情况下,这种情况是不应该出现或者不允许的,怎么解决呢?这里引入抽象工厂模式

抽象工厂模式

抽象工厂模式与工厂方法模式的最大区别就在于:工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。

关于产品等级产品族的概念,见下图:
这里写图片描述
对于工厂方法模式,每个工厂负责一个产品等级,各自生产零件,最后由总工厂组合成产品。而抽象工厂模式,则是一个总工厂负责统筹,总工厂下面的子工厂各自负责一个品族,生成产品,最后由是由总工厂将产品交付给客户。
这里写图片描述
代码实现如下:
底盘和引擎的实现和上面的工厂方法模式一样,不再贴出了。
抽象工厂、Benz工厂和BMW工厂:

public interface AbstractFactory {
    Chassis createChassis();
    Engine createEngine();
}

public class BenzFactory implements AbstractFactory {
    @Override
    public Chassis createChassis() { return new ChassisBenz(); }

    @Override
    public Engine createEngine() { return new EngineBenz(); }
}

public class BMWFactory implements AbstractFactory {

    @Override
    public Chassis createChassis() { return new ChassisBMW(); }

    @Override
    public Engine createEngine() { return new EngineBMW(); }
}

汽车工厂:

public class CarFactory {
    private Chassis chassis;
    private Engine engine;

    // 这里直接传入对应产品族的工厂实例,杜绝了产品等级不一致的问题
    public void createACar(AbstractFactory af){
        this.chassis = af.createChassis();
        this.engine = af.createEngine();
        System.out.println("A car is created.");
        System.out.printf("CHASSIS: %s\n", chassis.identify());
        System.out.printf("ENGINE: %s", engine.identify());
    }
}

客户:

public class Client {
    public void orderACart(AbstractFactory af){
        CarFactory cf = new CarFactory();
        cf.createACar(af);
    }
}

class ClientTest {
    public static void main(String[] args) {
        Client client = new Client();
        AbstractFactory af = new BMWFactory();
        client.orderACart(af);
    }
}

可以看到,客户使用抽象工厂来创建需要的对象,客户只是面向产品的接口编程,根本无需知道工厂的具体实现。也就是说,客户端从具体的产品实现中解耦。而且,由于具体工厂限制了产品族对中每个零件的产品等级,从而解决了上面产品等级不对应的问题,不会再出现Benz底盘装载BMW引擎的车了。

另外,抽象工厂模式实现了产品与工厂的解耦,所以支持增加产品族。例如我们要增加一个Porsche车的产品族,只需增加一个Porsche工厂实例,和对应的零件实例就可以了,也就是说,我们可以通过实现AbstractFactoryChassisEngine这几个接口就可以增加一个产品族。但如果想要增加产品等级,则需要修改工厂的具体实现。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值