创建型模式 - 工厂模式

系列文章目录



代码地址


一、工厂模式

1.1 什么是工厂模式?

  • 我们在创建对象时不会对客户端直接暴露创建逻辑,而是通过使用一个共同的接口根据不同的条件来指向具体想要创建的对象

1.2 为什么使用工厂模式?

  • 解耦:把对象的创建和使用的过程分开;
  • 降低代码重复:如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码;
  • 降低维护成本:由于创建过程都是由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建某个对象的地方逐个修正,只需要在工厂里面修改即可,降低维护成本;

1.3 工厂模式的分类

  • 简单工厂模式(Simple Factory),又称静态工厂方法模式(Static Factory Method Pattern);
  • 工厂方法模式(Factory Method),又称多态性工厂模式(Polymorphic Factory)或虚拟构造子模式(Virtual Constructor);
  • 抽象工厂模式(Abstract Factory),又称工具箱模式(Kit 或Toolkit);

二、简单工厂模式(Simple Factory)

  • 专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。
  • 它实质上是有一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)。
  • 工厂类是整个简单工厂模式的关键所在,它包含了必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建那个具体类的对象。
  • 用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象时如何创建以及如何组织的。

在这里插入图片描述

角色:

  • 工厂角色:简单工厂模式的核心,他负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象;
  • 抽象产品角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  • 具体产品角色:简单工厂的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例;
public class SimpleFactory {
    public static void main(String[] args) {
      BuildCarSimpleFactory carSimpleFactory = new BuildCarSimpleFactory();
      carSimpleFactory.newCar("Van").run();

      carSimpleFactory.newCar("Mini").run();
    }
}

/**
 *简单工厂,产品数量较少
 * 更多的产品则,违反开闭原则,对扩展开放,对修改关闭,应该扩展一个类来做,而不是修改示例中的条件判断
 */
class BuildCarSimpleFactory{

    //传递Class,通过反射创建,但是没有解决根本问题,创建小车步骤、厂商不同,所需的流程等等也不同不能直接反射直接创建
    public AbstractCar newCar(String carType){
        if("Van".equals(carType)){
            return new VanCar();
        }else if("Mini".equals(carType)){
            return new MiniCar();
        }else {
            return null;
        }
    }
}

abstract class AbstractCar{
    String engine;
    public abstract void run();
}

class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单缸柴油机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 哒哒哒哒..");
    }
}

class MiniCar extends AbstractCar{
    public  MiniCar(){
        this.engine = "四缸发动机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 嘟嘟嘟嘟..");
    }
}
  • 简单工厂模式能够根据外界给定的信息,决定究竟应该创建那个具体类的对象,通过它外界可以从直接创建具体产品对象的尴尬局面中摆脱出来,外界与具体的类隔离开来,耦合性低,明确区分了各自的职责和权力,有利于这个软件体系结构的优化;

  • 因为工厂类集中了所有产品的创建逻辑,一旦不能正常工作,整个系统都要收到影响,系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂,违背了“OCP 开闭原则”;

  • 适用范围:

    • 工厂类负责创建爱你的对象较少,客户只知道传入了工厂类的参数,对于如何创建(逻辑)不关系;

三、工厂方法(Factory Method)

  • 工厂方法模式应该是工厂模式家族中用的最多的模式,一般项目中存在最多的就是这个模式;
  • 工厂方法模式是简单工厂的进一步深化,在工厂方法模式中,我们不在提供一个统一工厂类创建所有的对象,而不是针对不同的对象提供不同的工厂。也就是说,每个对象都有约过与之对应的工厂;

如果是以前简单工厂则需要改:

在这里插入图片描述

采用工厂方法模式:

  • 因为简单工厂模式中工厂方法写死了,需要把工厂提升层次(定义抽象),给提升为接口或者抽象类,多实现,多实现就会有多功能,更利于扩展

在这里插入图片描述

角色:

  • 抽象工厂角色:是工厂方法的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口;
  • 具体工厂角色:这个是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且收到应用程序调用以创建某一种产品对象;
  • 抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口;
  • 具体产品角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,他们之间往往一一对应;
public class SimpleFactory1 {
    public static void main(String[] args) {
        AbstractCarFactory vanCarFactory = new WuLingVanCarFactory();
        vanCarFactory.newCar().run();
        AbstractCarFactory miniCarFactory = new WuLingMiniCarFactory();
        miniCarFactory.newCar().run();
    }
}

public abstract class AbstractCar {
    String engine;
    public abstract void run();
}
public abstract class AbstractCarFactory {
    public  abstract AbstractCar newCar();
}

public class MiniCar extends AbstractCar{
    public  MiniCar(){
        this.engine = "四缸发动机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 嘟嘟嘟嘟..");
    }
}
public class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单缸柴油机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 哒哒哒哒..");
    }
}

public class WuLingMiniCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}
public class WuLingVanCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new VanCar();
    }
}
  • 在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类;
  • 在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏替换原则;
  • 将创建对象的任务委托给多个工厂子类中的一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时在动态制定,课将具体工厂的类名存储在配置文件或数据库中;
  • 这样每个工厂负责一种类型,在增加其他类型只需要添加一个工厂类及具体的工厂类即可,符合开闭原则;
  • 存在问题:产品单一;当产品种类过多时候,系统复杂度增加,并且还可能违反开闭原则,如何解决,抽象工厂;

四、抽象工厂(Abstract Factory)

  • 在工厂方法模式中,我们生产的都是同一类产品;

  • 抽象工厂模式是工厂方法的进一步深化,在这个模式中的工厂类不单单可以创建一种产品,而是可以创建一组产品;

在这里插入图片描述

/**
 * 五菱总厂规范
 */
public abstract class WuLingFactory {

    abstract AbstractMask newAMask();

    abstract AbstractCar newCar();

}

/**
 * 具体工厂,只造口罩
 */
public class WuLingWuHanMaskFactory extends WuLingFactory{
    @Override
    AbstractMask newAMask() {
        return new N95Mask();
    }

    @Override
    AbstractCar newCar() {
        return null;
    }
}
/**
 * 具体工厂,只造车
 */
public class WuLingVanCarFactory extends WuLingFactory{
    @Override
    AbstractMask newAMask() {
        return null;
    }

    @Override
    AbstractCar newCar() {
        return new VanCar();
    }
}
public class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单缸柴油机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 哒哒哒哒..");
    }
}
public class N95Mask extends AbstractMask{
    public N95Mask(){
        this.price = 100;
    }
    @Override
    public void protectMe() {
        System.out.println(String.format("%s ,超级防护....", "N95 Mask"));
    }
}

还可以继续抽象:

在这里插入图片描述

/**
 * @Description: 五菱总厂规范
 * @Author: dozezz
 * @Date: 2021/7/12 21:03
 * @Version: 1.0
 */
public abstract class WuLingFactory {

    abstract AbstractMask newAMask();

    abstract AbstractCar newCar();

}
/**
 * @Description: 五菱汽车集团(归属五菱总厂)
 * @Author: dozezz
 * @Date: 2021/7/12 21:26
 * @Version: 1.0
 */
public abstract class WuLingCarFactory extends WuLingFactory{
    @Override
    AbstractMask newAMask() {
        return null;
    }

    @Override
    abstract  AbstractCar newCar() ;
}
/**
 * @Description: 五菱口罩集团(归属五菱总厂)
 * @Author: dozezz
 * @Date: 2021/7/12 21:32
 * @Version: 1.0
 */
public abstract class WuLingMaskFactory extends WuLingFactory{
    @Override
    abstract  AbstractMask newAMask() ;

    @Override
    AbstractCar newCar() {
        return null;
    }
}
/**
 * @Description:
 * @Author: dozezz
 * @Date: 2021/7/12 21:28
 * @Version: 1.0
 */
public class WuLingVanCar1Factory extends WuLingCarFactory{

    @Override
    AbstractCar newCar() {
        return new VanCar();
    }
}

/**
 * @Description: 具体实现,口罩工厂
 * @Author: dozezz
 * @Date: 2021/7/12 21:34
 * @Version: 1.0
 */
public class WuLingHangzhouMaskFactory extends WuLingMaskFactory{
    @Override
    AbstractMask newAMask() {
        return new CommonMask();
    }
}
/**
 * @Description:
 * @Author: dozezz
 * @Date: 2021/7/12 17:01
 * @Version: 1.0
 */
public class CommonMask extends AbstractMask{
    public  CommonMask(){
        this.price = 1;
    }

    @Override
    public void protectMe() {
        System.out.println(String.format("%s ,简单好用,及时更换....", "Common Mask"));
    }
}
/**
 * @Description:
 * @Author: dozezz
 * @Date: 2021/7/12 20:07
 * @Version: 1.0
 */
public class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单缸柴油机";
    }
    @Override
    public void run() {
        System.out.println(this.engine + "--> --> 哒哒哒哒..");
    }
}

  • 当抽象工厂模式中每一个具体的工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式
  • 当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式

五、 参考文献

  • https://www.bilibili.com/video/BV1G4411c7N4?p=37&spm_id_from=pageDriver
  • https://www.cnblogs.com/maohuidong/p/7843807.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值