工厂模式
核心本质:
- 实例化对象不使用new,用工厂方法代替。
- 将选择实现类,创建对象统一管理和控制。从而将调用者与实现类解耦。
作用:
- 实现了创建者和调用者的分离。
分类:
- 简单工厂模式:用于生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码)。
- 工厂方法模式:用于生产同一等级结构中的固定产品(支持增加任意产品)。
- 抽象工厂模式:围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
OOP七大原则:
- 开放封闭原则(OCP:Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。
- 依赖倒转原则(DIP:Dependency Inversion Principle):要针对接口编程,不要针对实现编程。
- 迪米特原则或者最少知识原则(LOD:Law of DemeterPrinciple):只与你直接的朋友通信,而避免和陌生人通信。
- Liskov替换原则(LSP:Liskov Substitution Principle):继承思想的基础。只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,软件单位的功能不会受到影响时,基类才真正被复用,而衍生类也才能够在基类的基础上增加新的行为。
- 接口隔离原则(IIP:Interface Isolation Principle):接口功能单一,避免接口污染。(实现:一个类对另一个类的依赖性应当是建立在最小的接口上的,使用多个专门的接口比使用单一的总接口要好)
- 单一职责原则(SRP:Single Responsibility Principle):就一个类而言,应该仅有一个引起它变化的原因。如果一个类的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会抑制这个类完成其他职责的能力。
- 合成/聚合复用原则(CARP:Composite/Aggregate Reuse Principle):设计模式告诉我们对象委托优于类继承,从UML的角度讲,就是关联关系优于继承关系。尽量使用合成/聚合、尽量不使用继承。(实现:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,以整合其功能)
//车的抽象接口
public interface Car {
void name();
}
//车的实现类 五菱
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱宏光");
}
}
//车的实现类 特斯拉
public class Tesla implements Car {
@Override
public void name() {
System.out.println("特斯拉");
}
}
一般使用模式
//消费者
public class Consumer {
public static void main(String[] args) {
Car car = new WuLing();
Car car2 = new Tesla();
car.name();
car2.name();
}
}
这种一般的方式中,调用者和实现类之间就会有很强的依赖性。
简单工厂模式(静态工厂模式)
方式一:
//车工厂类(简单工厂类)
public class CarFactory {
//获取车的方法
public static Car getCar(String name) {
Car car = null;
if (name != null) {
//通过name的不同返回不同车的实现类
if (name.equals("五菱")) {
car = new WuLing();
} else if (name.equals("特斯拉")) {
car = new Tesla();
}
}
return car;
}
}
//消费者
public class Consumer {
public static void main(String[] args) {
//在工厂中直接获取
Car car = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car.name();
car2.name();
}
}
方式二:
//车工厂类(简单工厂类)
public class CarFactory {
//获取五菱的方法
public static Car getWuLing(){
return new WuLing();
}
//获取特斯拉的方法
public static Car getTesla(){
return new Tesla();
}
}
与一般使用方式的效果一致,但是这样就将实现类和调用者解耦了,两者之间就没有直接的关系了,而是通过第三方工厂间接的方式产生联系,但是这样也有一些缺陷,如果扩展其他实现类,我们就需要在原代码中更改,才能实现对应的解耦,这种方式就不符合OOP原则的开闭原则,它的扩展就是修改。
工厂方法模式
将所有的工厂再抽取成一个超级工厂
//车工厂 工厂方法模式
public interface CarFactory {
Car getCar();
}
//特斯拉车工厂
public class TeslaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}
//五菱车工厂
public class WuLingFactory implements CarFactory {
@Override
public Car getCar() {
return new WuLing();
}
}
//通过对应的车工厂去获取对应的车
Car car = new WuLingFactory().getCar();
Car car2 = new TeslaFactory().getCar();
car.name();
car2.name();
这里就一个工厂对应了一个实现类,对应的工厂只需实现工厂的接口,它就专注的创造对应的车,相比于上面的方式,有了更好的扩展性。
对比
简单工厂模式 | 工厂方法模式 | |
---|---|---|
结构复杂度 | ↑ | ↓ |
代码复杂度 | ↑ | ↓ |
编程复杂度 | ↑ | ↓ |
管理复杂度 | ↑ | ↓ |
如果是根据设计原则来说:推荐工厂方法模式,但是根据实际业务(实际业务更注重简单通俗)来说:更推荐简单工厂模式。