工厂设计模式
分类
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式可以分为三类:
- 简单工厂方法——Simple Factory
- 工厂方法模式——Factory Method
- 抽象工厂方法——Abstract Factory
1.简单工厂设计模式
所谓的简单工厂就是通过一个工厂类来实现产品的实例化,通常可以在工厂类中定义一个静态方法,通过传入相应的参数来产生相应的产品对象。
//定义一个产品接口
interface IProduct{
public void desc();
}
//定义一个产品A
class ProductA implements IProduct{
public void desc() {
System.out.println("Product A");
}
}
//定义一个产品B
class ProductB implements IProduct{
public void desc() {
System.out.println("Product B");
}
}
//定义一个产品C
class ProductC implements IProduct{
public void desc() {
System.out.println("Product C");
}
}
//定义工厂类
class SimpleFactory {
public static final int PRODUCT_A = 1;
public static final int PRODUCT_B = 2;
public static final int PRODUCT_C = 3;
public static IProduct createProduct( int flag) {
switch(flag) {
case PRODUCT_A:
return new ProductA();
case PRODUCT_B:
return new ProductB();
case PRODUCT_C:
default:
return new ProductC();
}
}
}
public class FactoryMode {
public static void main(String[] args) {
// 简单工厂设计模式:实例化产品A
IProduct iproduct = SimpleFactory.createProduct(SimpleFactory.PRODUCT_A);
iproduct.desc();
}
}
使用场景:工厂类负责创建的对象比较少,客户只需要传入工厂类参数,对于如何创建对象(逻辑)不关心。简单工厂模式很容易违反高内聚低耦合的原则,因此一般只在很简单的情况下使用。
优点:最大的优点在于工厂类中包含了必要的逻辑,根据客户需要的逻辑动态实例化相关的类。
缺点:扩展性差,每次新增产品时都需要修改工厂类方法。
此外简单工厂还有一种写法:通过多个静态方式实现
class SimpleFactory {
public static IProduct createProductA() {
return new ProductA(); //生产产品A
}
public static IProduct createProductB() {
return new ProductB(); //生产产品B
}
public static IProduct createProductC() {
return new ProductC(); //生产产品C
}
}
public class FactoryMode {
public static void main(String[] args) {
// 简单工厂设计模式:实例化产品A
IProduct iproduct = SimpleFactory.createProductA();
iproduct.desc();
}
}
这种写法的好处就是在新增产品时,只需要增加相应的静态方法即可,而不需要修改原有方法的逻辑。
2.工厂方法模式
简单说就是一种产品对应一个工厂类,这些工厂类都继承/实现一个抽象工厂类/工厂接口。
如下图所示:
代码如下:
创建工厂类
//产品A对应的工厂方法
class FactoryProductA implements IFactory{
@Override
public IProduct createProduct() {
return new ProductA();
}
}
//产品B对应的工厂方法
class FactoryProductB implements IFactory{
@Override
public IProduct createProduct() {
return new ProductB();
}
}
//产品C对应的工厂方法
class FactoryProductC implements IFactory{
@Override
public IProduct createProduct() {
return new ProductC();
}
}
客户端
public class FactoryMode {
public static void main(String[] args) {
// 工厂方法:实例化产品A
FactoryProductA fpa = new FactoryProductA();
ProductA pA = (ProductA)fpa.createProduct();
pA.desc();
// 工厂方法:实例化产品B
FactoryProductB fpb = new FactoryProductB();
ProductB pb = (ProductB)fpb.createProduct();
pb.desc();
}
}
优点:创建对象的接口,让子类决定具体实例化的对象,把简单的内部逻辑判断移到了客户端。扩展性高,想要增加一个产品,只要扩展一个工厂类就可以。工厂方法模式克服了简单工厂所违背的开闭原则的缺点,又保持了封装对象创建过程的优点。
缺点:当产品种类非常多时,需要建立非常多的工厂类,这不是我们希望的。
使用场景
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
- 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。
3.抽象工厂方法
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。
如下图所示:
还是以汽车为例,汽车A配备A型号发动机+A型号空调,汽车B配备B型号发动机+B型号空调,根据客户需求生产这种车。
定义产品1—空调(Aircondition):
interface IAirCondition{
public void desc();
}
class AirConditionA implements IAirCondition{
@Override
public void desc() {
System.out.println("Air Condition A");
}
}
class AirConditionB implements IAirCondition{
@Override
public void desc() {
System.out.println("Air Condition B");
}
}
定义产品2—引擎(Engine):
interface IEngine{
public void desc();
}
class EngineA implements IEngine{
@Override
public void desc() {
System.out.println("Engine A");
}
}
class EngineB implements IEngine{
@Override
public void desc() {
System.out.println("Engine B");
}
}
定义工厂类:
interface IFactory{
public IEngine createEngine();
public IAirCondition createAirConditon();
}
//CarA对应的工厂方法
class FactoryCarA implements IFactory{
@Override
public IEngine createIEngine() {
return new EngineA();
}
@Override
public IAirCondition createAirConditon() {
return new AirConditionA();
}
}
//CarB对应的工厂方法
class FactoryCarB implements IFactory{
@Override
public IEngine createIEngine() {
return new EngineB();
}
@Override
public IAirCondition createAirConditon() {
return new AirConditionB();
}
}
客户端
public class FactoryMode {
public static void main(String[] args) {
FactoryCarA fa = new FactoryCarA();
fa.createAirConditon().desc();
fa.createEngine().desc();
FactoryCarB fb = new FactoryCarB();
fb.createAirConditon().desc();
fb.createEngine().desc();
}
}
使用场景:当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。
ps:理解产品族和等级结构概念。
(1) 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
(2) 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中,海尔电视机、海尔电冰箱构成了一个产品族。
以下为例:
在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而2.0排量车和2.4排量车则称为两个不同的产品族。再具体一点,2.0排量两厢车和2.4排量两厢车属于同一个等级结构,2.0排量三厢车和2.4排量三厢车属于另一个等级结构;而2.0排量两厢车和2.0排量三厢车属于同一个产品族,2.4排量两厢车和2.4排量三厢车属于另一个产品族。
明白了等级结构和产品族的概念,就理解工厂方法模式和抽象工厂模式的区别了,如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。在本例中,如果一个工厂模式提供2.0排量两厢车和2.4排量两厢车,那么他属于工厂方法模式;如果一个工厂模式是提供2.4排量两厢车和2.4排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。