设计模式学习笔记-工厂模式
作用
- 实现了创建者和调用者的分离
- 详细分类
- 简单工厂模式
- 用来生产同一等级结构中的任意产品(对于增加新的产品,必须要扩展已有的代码)
- 工厂方法模式
- 用来生产同一等级结构中的固定产品(支持增加任意产品)
- 抽象工厂模式
- 围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂
- 简单工厂模式
在工厂模式中该满足的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方法