一.基础概念
1.作用:
实现了创建者和调用者的分离(创建型模式)。
2.核心本质:
实例化对象不使用new,用工厂方法代替;
将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。
3.三种模式:
简单工厂模式:用来生产同一等级结构中的任意产品(对于新增的产品,需要覆盖已有代码);
工厂方法模式:用来生产同一等级结构中的固定产品(支持增加任意产品);
抽象工厂模式:围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。
4.满足的 OOP七大原则:
开闭原则:一个软件的实体应当对扩展开放,对修改关闭;
依赖倒转原则:要针对接口编程,不要针对实现编程;
迪米特法则:只与你直接的朋友通信,而避免和陌生人通信。
二. 简单工厂模式(静态工厂模式)
准备如下几个汽车类:
public interface Car {
void buy();
}
public class Aito implements Car{
@Override
public void buy() {
System.out.println("购买了一辆问界");
}
}
public class Luxeed implements Car{
@Override
public void buy() {
System.out.println("购买了一辆智界");
}
}
原来消费者需要购买汽车的时候的,需要如下操作:
public class Consumer {
public static void main(String[] args) {
Car car1 = new Aito();
Car car2 = new Luxeed();
car1.buy(); // 购买了一辆问界
car2.buy(); // 购买了一辆智界
}
}
这个操作需要我们去了解所有的接口、实现类(Aito类和Luxeed类),如果不知道具体信息就没法进行下一步操作,但是在真实的场景中,我们只需要Car类,它里面有什么东西我们并不需要了解;
比如现实中买车,想买一个问界,并不需要知道车是怎么生产的,只需要花钱买就行了,但是这里使用的new相当于就是自己造的车,而实际中汽车是通过工厂来的。
接下来,创建一个工厂:
public class CarFactory {
public static Car getcar(String car) {
if (car.equals("问界")) {
return new Aito();
} else if (car.equals("智界")) {
return new Luxeed();
} else {
return null;
}
}
}
通过工厂进行购买汽车:
public class Consumer {
public static void main(String[] args) {
Car car1 = CarFactory.getcar("问界");
Car car2 = CarFactory.getcar("智界");
car1.buy(); // 购买了一辆问界
car2.buy(); // 购买了一辆智界
}
}
假如Aito()里面有很多参数,通过new的方式就需要带大量参数,这种带大量参数的创建方式,自己去写很繁琐的,但是我们写一个车工厂,它就可以帮我们做这些繁琐的事,它把事情做完,我们根本不用关心里面是否有其他细节,只需要直接调用即可,这是一种最快捷的方法,如下图所示:
但是它也有不好的地方,如果我们还需要添加一个享界,那么还需要创建一个Stelato类,并且实现Car接口,然后还需要在CarFactory中添加一个else if来修改工厂的逻辑,这也就是说,如果新增加一个产品,如果不修改代码,是做不到的,但是这样就不满足开闭原则了。
但是在大多数情况下,我们使用的就是简单工厂模式,因为要满足开闭原则,就需要付出更多的代价,也就是使用工厂方法模式。
二.工厂方法模式
同样需要准备简单工厂模式中的Car、Aito、Luxeed三个类
接下来,创建一个car工厂:
public interface CarFactory {
Car getCar();
}
创建Aito工厂:
public class AitoFactory implements CarFactory{
@Override
public Car getCar() {
return new Aito();
}
}
创建Luxeed工厂:
public class LuxeedFactory implements CarFactory{
@Override
public Car getCar() {
return new Luxeed();
}
}
此时消费者购买汽车:
public class Consumer {
public static void main(String[] args) {
Car car1 = new AitoFactory().getCar();
Car car2 = new LuxeedFactory().getCar();
car1.buy(); // 购买了一辆问界
car2.buy(); // 购买了一辆智界
}
}
只需要找到对应汽车的工厂即可,此时如果需要新增一个车,只需要实现Car、CarFactory接口即可,不需要修改原来的类,这就满足了开闭原则。
例如增加享界汽车:
public class Stelato implements Car{
@Override
public void buy() {
System.out.println("购买了一辆享界");
}
}
public class StelatoFactory implements CarFactory{
@Override
public Car getCar() {
return new Stelato();
}
}
此时购买享界:
public class Consumer {
public static void main(String[] args) {
Car car = new StelatoFactory().getCar();
car.buy(); // 购买了一辆享界
}
}
虽然现在满足的开闭原则,但是明显发现代码量变多了很多,以后每多一个车,都要多一个扩展类,这样的扩展类就会越来越庞大,这样实现起来,反而是非常麻烦,如下图所示:
所以,大多少情况下,我们还是会使用简单工厂模式。
(1)从结构复杂度、代码复杂度、编程复杂度、管理上的复杂度来看,都是简单工厂模式更合适;
(2)根据设计原则,需要采用工厂方法模式,但是根据实际义务一般会采用简单工厂模式。
三.总结
1.简单工厂模式(静态工厂模式):虽然某种程度上不符合设计原则,但实际使用最多;
2.工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展;
3.抽象工厂模式:不可以增加产品,可以增加产品族。
PS:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式;有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new
就可以完成创建的对象,无需使用工厂模式;如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度
四.应用场景
1.日志记录时可以让用户选择记录到什么地方;
2.数据库访问时可以让用户选择具体使用什么数据库;
3.设计一个连接服务,需要访问多种协议时,可以把多种协议定作为产品类,共同实现一个接口,供用户选择。
标签:buy,彻底,Car,模式,工厂,玩转,new,public From: https://blog.csdn.net/BestandW1shEs_lsy/article/details/143836541