设计模式演化之工厂模式

本文深入探讨了设计模式中的工厂模式,从简单工厂模式开始,阐述其定义、演化、实现过程和优缺点。接着介绍了工厂方法模式,分析了其定义、适用场景及实现方式,以解决简单工厂模式的局限性。最后讨论了抽象工厂模式,解释了它的定义、应用场景以及如何解决产品种类过多的问题。通过这两种模式,可以更好地管理和创建相关或依赖对象。
摘要由CSDN通过智能技术生成

简单工厂模式

定义

由一个工厂类根据参数来决定创建哪一种产品的实例

演化

1.我需要一台电脑用来工作
实现:先定义一个Computer类,然后调用它的启动方法

public class Computer {
    private String name;
    public Computer(String name) {
        this.name = name;
    }

    public void start() {
        System.out.println(name);
    }
}
public void startWork() {
    // 这里只是new了一个Computer对象,实际它的创建过程应该十分复杂
    Computer computer = new Computer("computer");
    computer.start();
}

2.Computer的创建过程复杂多变,我不会制造电脑(即不知道如何创建一个Computer对象),但是厂商能制造电脑,我去他们那里买就行了。
实现:新增厂商类,厂商需要知道如何生产电脑,它有创建Computer的方法。

public class ComputerFactory {
    public Computer getComputer() {
        Computer computer = new Computer("computer");
        return computer;
    }
}
public void startWork() {
    ComputerFactory factory = new ComputerFactory();
    Computer computer = factory.getComputer();
    computer.start();
}

3.这家厂商能够生产A,B,C三种型号的电脑,因此我买之前需要告诉他我需要哪一种。
实现:
(1) Computer作为超类,新增ComputerA,ComputerB、ComputerC具体产品类。
(2) 改造ComputerFactory的getComputer()方法,它能根据传入的参数决定返回哪一个具体产品类的对象

public class ComputerFactory {
    public class ComputerFactory {
    public Computer getComputer(String type) {
        Computer computer = null;
        switch (type) {
            case "A":
                computer = createComputerA();
                break;
            case "B":
                computer = createComputerB();
                break;
            case "C":
                computer = createComputerC();
                break;
            default:
                break;
        }
        return computer;
    }
    
    public Computer createComputerA() {
        return new ComputerA("computerA");
    }
    
    public Computer createComputerB() {
        return new ComputerB("computerB");
    }
    
    public Computer createComputerC() {
        return new ComputerC("computerC");
    }
}
}
public void startWork() {
    ComputerFactory factory = new ComputerFactory();
    Computer computer = factory.getComputer("B");
    computer.start();
}

至此,一个简单工厂模式的过程就完成了。当然所有的对象创建都需要依赖于getComputer(),一旦调用放传入的type是工厂类无法识别的,就只能返回一个null了。为了避免这种情况,需要告诉调用方改工厂类所支持的type。当然也可以删除getComputer()方法,而让调用方直接通过createComputerX()来获取其想要的对象。

实现过程

(1) 定义抽象产品类
(2) 定义各个实际产品类
(3) 定义一个工厂类,工厂类中保存有各个实际产品类的创建过程
(4) 调用方通过工厂类来获取产品对象

适用类特点

所谓简单工厂模式,顾名思义,现实生活中的简单工厂通常只能生产一种产品,且这种产品只有一种或有限的几种型号。同种型号的产品虽然可以有很多个,但是这些产品的规格参数都是一模一样的,生产过程也是一样的。将一个类比作一个产品,就可以得出这个类应该具有的性质:
(1) 一个工厂只能生产一种产品:产品类应该有一个共同的父类
(2) 该产品可以有几种不同的型号:产品类有几个不同的子类
(3) 同种型号的产品规格参数应该相同:通过某一个子类创建的对象相同
(4) 产品的生产比较复杂,外界很难自己制造,需要到工厂里买:产品类的创建过程比较复杂,调用处使用困难,需要从工厂类中取。
(5) 工厂新增了一个产品流水线:新增产品类型时,需要新定义一个子类,并在工厂类增加一个创建方法。

优点

(1) 调用者可以直接使用工厂类的方法来创建对象,降低了耦合
(2) 调用者无需关心对象的创建过程,和各种参数信息。

缺点

(1) 如果增加新的产品类,则需要修改工厂类
(2) 当需要创建的类型过多时,所有的对象创建方式都放在了工厂中,导致工厂类庞大

工厂方法模式

定义

比较与简单工厂模式,抽象出工厂类,让其子类决定实例化哪一个类

场景

通过简单工厂模式基本已经满足了常见的情况。但是它描述的情况还是过于简单。而且还留下了一些缺陷,结合简单工厂模式中的场景可知:
(1) Factory类的职责过重,所有产品的创建都集中到了这里。
(2) Factory类需要经常扩展,每次新增产品都需要修改Factory类

当产品的类型数量有限且不需要频繁变更的时候,这两个缺陷可以忽略。当产品的数量级较大,且频繁增删时,缺陷将被无限放大。那么我们可以将Factory作为一个超类抽象出来,它并不具备创建任何产品的功能。而是需要具体的子类去实现,每一个子类都具备创建其对应产品的功能。如此每个具体Factory的职责就被减轻了。当新增产品时,也是通过新增Factory的实现类来解决,避免了对已有实现类的修改。

实现

1.定义抽象产品类

public class Computer {
    private String name;
    public Computer(String name) {
        this.name = name;
    }

    public void start() {
        System.out.println(name);
    }
}

2.定义具体产品类,当新增具体产品类时,在这里定义

public class HPComputer extends Computer {
    public HPComputer(String name) {
        super(name);
    }
}

3.定义抽象工厂类

public abstract class AbstractComputerFactory {
    public abstract Computer getComputer();
}

4.定义实际工厂类,当新增具体产品类时,在这里新增对应的具体工厂类

public class HPFactory extends AbstractComputerFactory {
    @Override
    public Computer getComputer() {
       retur HPComputer("HPComputer");
    }
}

5.在需要的地方调用

public class MethodClient {
    public static void startWork() {
        AbstractComputerFactory factory = new HPFactory();
        Computer computer = factory.getComputer();
        computer.start();
    }
}

抽象工厂模式

定义

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

场景

工厂方法模式简单工厂模式职责过重和不易扩展的问题。但依然不能充分应对开发中的各种场景。例如:
买电脑还需要与它配套的键盘鼠标,这是一个不能继承自Computer的新类,需要重新定义一个Mouse基类,这种情况AbstractComputerFactory是不够用的。需要再定义一个AbstractMouseFactory,并进行相应的扩展。这两个产品族密切相关,经常伴生出现,如果分开各自创建相应的产品对象,将会使得调用的过程复杂化,也会产生不必要的混乱。解决这种多个相关对象的创建问题,就需要用到抽象工厂模式了。
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。简单理解就是:通过工厂模式来管理产品的创建,由于工厂类过多,类型不尽相同,又需要通过超级工厂来管理工厂类的创建。这是一个双重的工厂模式。

实现 多产品族

1.一个完整的抽象工厂模式目录示例
在这里插入图片描述
(1) 目录下包含computer和mouse两个包和一个FactoryProducer类。代表着可以通过FactoryProducer获取ComputerFactory和MouseFactory。当需要新增一个产品族——键盘时:

  • 新建一个keyboard包,其下属目录结构与computer类似。
  • 在FactoryProducer中新增相应的方法getKeyBoardFactory()。

(2) 每个产品族下属的结构是一致的,以computer为例。Computer为所有产品的基类,AbstractComputerFactory的是所有工厂的基类。所有的实际工厂类都放在factory包中,所有的实际产品类都放在product中。且两者之间为一对一的关系。新增一个品牌如Lenovo:

  • 需要在product中增加LenovoComputer,在factory中新增LenovoComputerFactory。
  • FactoryProducer中的getComputerFactory()方法新增获取LenovoComputerFactory的情况。
解决产品种类过多问题

工厂方法模式的易于扩展也带来了一定的隐患。由于每个实际工厂类的职责单一,在产品数量级达到一定程度时,就会扩展出大量的实际工厂类。

例如:真正的电脑是要分很多品牌的,如联想,惠普,戴尔,机械革命等等,每个品牌下又含有多种型号,于是Computer的数量级将会变成

种类 = 品牌 * 型号

它的种类数量级就过高了。如果按照简单工厂模式的写法,ComputerFactory里将会集成很多个创建方法,调用方想要找到需要的创建方法无异于大海捞针。由于产品种类变化频繁,ComputerFactory的开发者也需要频繁地做出相应修改。无论对于使用还是扩展,简单工厂模式都已经不够用了。如果是按照工厂方法模式的写法,每个工厂类都对应到一个具体Computer类的创建,又容易创建上千个工厂类。
如果能够对Computer进行二次分类,如按照品牌分类,把不同品牌的Computer当做不同两个不同的产品族。就能减少每个产品族下种类的数量。

实现 多品牌多种类

1.这种情况下的目录结构如下所示
在这里插入图片描述
与多产品族的实现几乎没有区别,这里只是对一个产品族的产品进行了二次划分,将不同品牌的产品也当做多个产品族来处理,从而解决了单纯使用工厂方法模式导致Factory过多的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值