工厂模式的三种模式分述
在工厂模式开发中,分为三种:普通工厂模式(simple factory)、工厂方法模式(factory method)、抽象工厂模式(abstract factory)
1. 普通工厂模式:
顾名思义,这个模式本身很简单,而且使用在业务较简单的情况下(非绝对),由三小部分组成
1.1 构成
- 工厂类 包含一定的业务逻辑和判断逻辑,来具体实例化某一功能
- 具体产品抽象类 产品抽象类是具体产品实现类的父类,可以为抽象类 也可以为接口,下面的代码将以接口形式演示
- 具体产品实现类 工厂类所创建的对象就是此角色的实例。
1.2 代码 实现一个买车的案例
具体产品抽象类 (接口形式)
/**
* 具体产品抽象类 定义接口
*
* @author san.liu
*/
public interface CarAbstract {
public String getCarName();
}
具体产品实现类
/**
* 具体产品实现类 (跑车)
*
* @author san.liu
*/
public class RunCarAbstractImpl implements CarAbstract {
public String getCarName() {
return "我购买的是跑车";
}
}
工厂类(业务指向)
/**
* 简单工厂
*
* @author san.liu
*/
public class SimpleCarFactory {
public CarAbstract getCar(Class<?> classt) throws Exception {
if (SuvCarAbstractImpl.class.getName().equals(classt.getName())) {
return new SuvCarAbstractImpl();
}
if (RunCarAbstractImpl.class.getName().equals(classt.getName())) {
return new RunCarAbstractImpl();
} else {
throw new Exception("指定购车类型ERROR");
}
}
}
测试(test)
public static void main(String[] args)throws Exception {
SimpleCarFactory simpleCarFactory = new SimpleCarFactory();
CarAbstract carAbstract = simpleCarFactory.getCar(SuvCarAbstractImpl.class);
System.out.println(carAbstract.getCarName());
}
log:
我购买的是SUV
Process finished with exit code 0
上面测试代码中可以看到实例化了一个工厂类(SimpleCarFactory),个人感觉不太好,可以在改造一下,在工厂类添加一个静态方法。
工厂类 (改造后)
/**
* 简单工厂
*
* @author san.liu
*/
public class SimpleCarFactory {
public static CarAbstract getCar(Class<?> classt) throws Exception {
if (SuvCarAbstractImpl.class.getName().equals(classt.getName())) {
return new SuvCarAbstractImpl();
}
if (RunCarAbstractImpl.class.getName().equals(classt.getName())) {
return new RunCarAbstractImpl();
} else {
throw new Exception("指定购车类型ERROR");
}
}
}
test (改造后)
public static void main(String[] args)throws Exception {
CarAbstract carAbstract = SimpleCarFactory.getCar(SuvCarAbstractImpl.class);
System.out.println(carAbstract.getCarName());
}
log:我购买的是SUV
Process finished with exit code 0
效果是一样的
1.3 结论
使用了简单工厂模式后,我们的程序不在"有病",更加符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责"消费"产品,但是工厂部分好像不太理想,因为每增加一辆车,都要在工厂类中增加相应的商业逻辑和判断逻辑,这显自然是违背开闭原则的。所以引入了工厂方法模式
2.工厂方法模式
2.1构成
- 抽象工厂类 在基于普通工厂模式的基础上,在工厂类里添加了一个所有工厂的接口。也可以是抽象类,是具体工厂类的父类
- 具体工厂类 在基于普通工厂模式的基础上,把普通工厂的逻辑拆分为一个个的单元。
- 抽象产品类 产品抽象类是具体产品实现类的父类,可以为抽象类 也可以为接口,下面的代码将以接口形式演示
- 具体产品类 具体工厂类所创建的对象就是此角色的实例。
2.2 代码解释 (同上以购车为案例)
抽象工厂
/**
* 抽象工厂类
*
* @author san.liu
*/
public interface CarFactoryAbstract {
public CarAbstract getCar();
}
具体工厂
/**
* 具体工厂实现类 (跑车)
*
* @author san.liu
*/
public class RunCarFactoryAbstractImpl implements CarFactoryAbstract {
public CarAbstract getCar() {
return new RunCarAbstractImpl();
}
}
/**
* 具体工厂实现类(SUV)
*
* @author san.liu
*/
public class SuvCarFactoryAbstract implements CarFactoryAbstract {
public CarAbstract getCar() {
return new SuvCarAbstractImpl();
}
}
测试
public static void main(String[] args)throws Exception {
// CarAbstract carAbstract = SimpleCarFactory.getCar(SuvCarAbstractImpl.class);
// System.out.println(carAbstract.getCarName());
CarFactoryAbstract carFactoryAbstract = new RunCarFactoryAbstractImpl();
CarAbstract carAbstract = carFactoryAbstract.getCar();
System.out.println(carAbstract.getCarName());
}
log:
我购买的是跑车
Process finished with exit code 0
2.3 结论
如果使用普通工厂模式,新增车型的时候,我们需要修改普通工厂里的工厂类,这不是我们的初衷,也不符合符合开闭原则。但是工厂方法模式完全规避了这种现象,如果新增车型,我们只需要添加具体工厂实现类,以前的代码(车型)我们完全不用修改。所以,工厂方法模式完全符合开闭原则。但是,假设有100种车型,在工厂模式里就需要添加100个具体工厂类,这样显然是不合理的。所以在根据业务的情况下,选择合适的工厂模式。
3.抽象工厂模式
抽象工厂模式就是对工厂方法模式进行抽象,以上面的案例进行展开。跑车和suv属于汽车类,再将汽车以生产国家为单位进行分类,例如中国suv 、中国跑车、日本suv、日本跑车。
3.1构成
产品等级结构:定义一个SUV的抽象类,那么中国suv和日本suv都属于同级产品,也就是该抽象类的子类
产品族:指同一个工厂生产的,位于不同的产品等级结构的一组产品,比如中国跑车、中国SUV
抽象工厂:是一个接口,抽象工厂模式的核心,包含对多个产品等级结构的声明,任何工厂类都必须实现这个接口
具体工厂:是抽象工厂的实现,负责实例化某个产品族中的产品对象。例如中国生产跑车、SUV这些产品
3.2 使用条件
- 系统中有多个产品族,而系统一次只可能消费其中一族产品
- 同属于同一个产品族的产品以其使用
3.3总结
看过了前两个模式,对这个模式各个角色之间的协调情况应该心里有个数了,我就不举具体的例子了。只是一定要注意满足使用抽象工厂模式的条件哦,不然即使存在了多个产品树,也存在产品族,但是不能使用的