工厂模式

核心在于实现了创建者和调用者的分离
详细可以分为简单工厂模式、工厂方法模式、抽象工厂模式

抽象工厂模式在专门的笔记中

对应的三个原则是:
开闭原则:一个软件的实体应当对外扩展开放,对修改关闭
依赖倒转原则:要针对接口编程,不要针对实现编程
迪米特法则:只与你直接的朋友通信,避免和陌生人通信

核心本质与简介

本质:
1.不使用new来实例化对象,转而使用工厂方法代替
2.将选择实现类,创建对象统一管理和控制。从而将调用者和实现类解耦

简单工厂:用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有的代码)
工厂方法:用来生产同一等级结构中的固定产品
抽象工厂:围绕一个超级工厂来创建其他工厂,这个超级工厂又称为其他工厂的工厂

简单工厂/静态工厂

实现

核心在于实现在工厂中,使用者只需要调用
比如说我要造车

1
2
3
public interface Car {
void name();
}
1
2
3
4
5
6
public class Wulin implements Car{
@Override
public void name() {
System.out.println("五菱宏光");
}
}

我建造一个简单工厂,由它负责实现如何造车,而另外一端的使用者只需要知道自己要什么车即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class CarFactory {
//Car的工厂
public static Car getCar(String carName){
if(carName.equals("Wulin")){
return new Wulin();
}

if(carName.equals("Tesla")){
return new Tesla();
}

return null ;

}
}

使用者:

1
2
3
4
5
6
7
8
9
10
public class Test {
//自行new
Car car1 = new Wulin();
Car car2 = new Tesla();

//使用工厂创建!
Car car3 = CarFactory.getCar("Wulin") ;
//我们并不关心细节,则可以直接利用工厂调出要的car
//而实现创建的步骤则在工厂中实现
}

代码分析

实际上,这并没有很好地对应开闭原则,毕竟每加一个类型,我们都要去修改工厂中的相关方法
这也是简单工厂也叫静态工厂的原因:里面的方法都是静态的,通过接受的参数来返回不同的结果
这也导致了它不修改代码,就不能增加新产品

不过大部分时候是没有关系的,如果想要实现开闭原则,则需要付出更大的代价,那就是工厂方法模式了

工厂方法模式

工厂方法模式的代码量增加,但是它的横向扩展性极强,满足了开闭原则

实现

我们保留之前的Car接口,Wulin类和Tesla类
此时,我们不直接使用工厂,而是将工厂设置为一个接口,并让每一种车各自的工厂实现这个接口

1
2
3
4
5
//工厂方法模式
public interface CarFactory_Method {
//定义一个拿到车的方法,于是之后使用这个接口的类都要有这个方法了,之后把各种车的工厂分开,并实现这个接口
Car getCar();
}
1
2
3
4
5
6
7
public class TeslaFactory implements CarFactory_Method{
@Override
//在该工厂中即可得到我们的Tesla
public Car getCar() {
return new Tesla();
}
}
1
2
3
4
5
6
public class WulinFactory implements CarFactory_Method{
@Override
public Car getCar() {
return new Wulin();
}
}

于是,我们就可以利用各个工厂得到各个车

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test {
//自行new
Car car1 = new Wulin();
Car car2 = new Tesla();

//使用简单工厂创建!
Car car3 = CarFactory.getCar("Wulin") ;
//我们并不关心细节,则可以直接利用工厂调出要的car
//而实现创建的步骤则在工厂中实现

//使用工厂方法模式
Car car4 = new WulinFactory().getCar();
Car car5 = new TeslaFactory().getCar();
}

它的优势在哪呢,优势就在扩展,比如说我现在想加入一个新车,大众车
我们需要两步
1.写这个类

1
2
3
4
5
6
public class DaZhong implements Car{
@Override
public void name() {
System.out.println("大众");
}
}

2.写它的工厂

1
2
3
4
5
6
public class DaZhongFactory implements CarFactory_Method{
@Override
public Car getCar() {
return new DaZhong();
}
}

于是测试代码就又多了一种车,而这个过程中我们并没有修改之前的代码

1
2
3
public class Test {
Car car6 = new DaZhongFactory().getCar();
}

代码分析

和简单工厂相比,它的代码量很多很多,而且随着种类的增加,类也在增加
但是它带来的好处是不用修改原工厂代码,横向扩展简单

对比

实际上个人认为,简单工厂就够了,即使它不完全符合开闭原则
结构复杂度:简单工厂
代码复杂度:简单工厂
编程复杂度:简单工厂
管理复杂度:简单工厂

但工厂方法实现了原则

然而,在实际开发中,简单工厂的优势巨大,而开闭原则在这种情况并不一定要遵守,死遵守原则带来的代价往往高于简单工厂
所以,大部分时候还是简单工厂吧!

虽然有的时候要看原则,但是更多时候需要据情况考虑,而非只看原则规则。规则原则是死的,人是活的