设计模式学习笔记-工厂模式

设计模式学习笔记-工厂模式

作用

  • 实现了创建者和调用者的分离
  • 详细分类
    • 简单工厂模式
      • 用来生产同一等级结构中的任意产品(对于增加新的产品,必须要扩展已有的代码)
    • 工厂方法模式
      • 用来生产同一等级结构中的固定产品(支持增加任意产品)
    • 抽象工厂模式
      • 围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂

在工厂模式中该满足的OOP七大原则

  • 开闭原则
  • 依赖倒置原则
  • 迪米特法则

核心本质

  • 实例化对象不适用new,用工厂方法代替
  • 将选择实现类,创建对象统一管理和控制,从而将调用者和实现类解耦

以往的使用方式(以买车举例)

我们先定义一个车的接口,代表了我们所要买的东西是一辆车

public interface Car{
    void name();
}

接着我们去定义具体的车的类型,哪种车

public class Porsche implements Car{
    @Override
    public void name(){
        System.out.println("Porsche");
    }
}

接着是我们的消费者类,干这件事的主体

public class Consumer{
    public static void main(String[] args){
        Car porsche = new Porsche();
   
   		porsche.name();
    }
}

在这种情况下,我们必要要清楚该接口以及其所有的实现类,但在真实情况下,我们只需要知道其接口,即其主要是个什么东西,而不需要去知道其实现类。

简单工厂模式(静态工厂模式)

那么,去实现这样一种写法,我们就需要使用工厂模式。首先定义一个车的工厂:

public class CarFactory{
    
    // 我们根据客户需求的不同车的名字去获取该车
    public static Car getCar(String carName){
        if(carName.equals("Porsche"))
            return new Porsche();
        else if(carName.equals("Ferrari"))
            return new Ferrari();
        else
            return null;
    }
    
}

那么在消费者的类中,我们只需传入想要的东西的一些属性我们就可获得

public class Consumer{
    
    public static void main(String[] args){
        
        Porsche porsche = CarFactory.getCar("Porsche");
        Ferrari ferrari = CarFactory.getCat("Ferrari");
        ....
            
        Porsche.name();
        Ferrari.name();
        ....
            
    }
    
}

但是即便在这种情况下,这个CarFactory类仍然存在着问题,它并不满足开闭原则,即我们每想增加一种类型的车的时候,就需要在代码逻辑之间去增加、修改,代码的冗余度高而且对于代码的维护十分不便利,那我们该如何去优化这个工厂呢,有的人可能会想,那么在工厂中,对于客户想要什么类型的车就返回什么车就好了

public class CarFactory{
    public static Car getPorsche(){
        return new Porsche();
    }
    
    public static Car getFerrari(){
        return new Ferrari();
    }
}

在这种方式下,虽然优化了工厂,使我们在新增车辆种类时不必去修改原有的代码逻辑,但我们还是需要在该工厂中新增一个新的方法,仍然是不满足开闭原则,而简单工厂模式的弊端就是当增加一个新的产品时,如果不修改代码是做不到的

工厂方法模式

同样的,在这种模式下,我们仍需要车工厂,但是不同的是,我们不再是使用一个车工厂去生产所有的车,而是让每一个车有其对应的车工厂,那么首先我们定义一个接口,去规范所有的车工厂

public interface CarFactory{
    // 获取车辆
    Car getCar();
}

拿Porsche举例,要想获得指定的车,那么就需要指定的车工厂:

public class PorscheFactory implements CarFactory{
    
    // 获取Porsche
    @Override
    public Car getCar(){
        return new Porsche(); 
    }
}

那么在消费者想消费指定车辆时,只需从指定车工厂获取即可

public class Consumer{
    
    Public static void main(String[] args){
        Porsche porsche = new PorscheFactory().getCar();
        
        porsche.name();
    }
    
}

而在这种模式下,当我们想要新增一个车的种类(例如:Lambo)时,可以发现,我们只需增加一个Lambo的类,增加一个LamboFactory的类,而此时我们并没有去修改原来的代码,但弊端就是代码量显著提高了

两者区别

  • 结构复杂度上看

    • 简单工厂模式的结构复杂度显然是要低于工厂方法模式
  • 代码复杂度上看

    • 简单工厂模式的代码复杂度低于工厂方法模式
  • 编程复杂度

    • 简单工厂模式的编程复杂度低于工厂方法模式
  • 管理复杂度

    • 简单工厂模式因为所有的代码都集合在一个工厂中,管理起来是要低于工厂方法模式的

那么,综上来看,如果是根据设计原则,那么我们优先使用工厂方法模式,而如果是根据实际业务,我们优先使用简单工厂模式。

应用场景

  • JDK中Calendar的getInstance方法
  • JDBC中Connection对象的获取
  • Spring中IOC容器创建管理bean对象
  • 反射中Class对象中的newInstance方法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值