抽象工厂模式(Abstract Factory Pattern)
1. 抽象工厂模式的定义
抽象工厂模式(Abstract Factory Pattern)是一种比较常用的模式,其定义如下:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类)。
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
在场景类中,没有任何一个方法与实现类有关系,对于一个产品来说,我们只要知道它的工厂方法就可以直接产生一个产品对象,无须关心它的实现类。
1.1 代码示例
抽象类及接口
package com.qqxhb.pattern;
/**
* 产品接口
*
* @author Administrator
*
*/
public interface Product {
/**
* 输出产品信息抽象方法
*
*/
public abstract void printInfo();
/**
* 输出产品使用场景
*
*/
public abstract void printClassify();
}
package com.qqxhb.pattern;
/**
* 桌子抽象类
*
* @author Administrator
*
*/
public abstract class AbstractTable implements Product {
@Override
public void printInfo() {
System.out.println("Product Table");
}
}
package com.qqxhb.pattern;
/**
* 椅子抽象类
*
* @author Administrator
*
*/
public abstract class AbstractChair implements Product {
@Override
public void printInfo() {
System.out.println("Product Chair");
}
}
package com.qqxhb.pattern;
/**
* 产品工厂接口
*
* @author Administrator
*
*/
public interface ProductFactory {
/**
* 创建桌子
*
*/
public Product createTable();
/**
* 创建椅子
*
*/
public Product createChair();
}
实现类
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.AbstractChair;
/**
* 教室椅子
*
* @author Administrator
*
*/
public class ClassroomChair extends AbstractChair {
@Override
public void printClassify() {
System.out.println("Classroom");
}
}
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.AbstractTable;
/**
* 课桌
*
* @author Administrator
*
*/
public class ClassroomTable extends AbstractTable {
@Override
public void printClassify() {
System.out.println("Classroom");
}
}
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.Product;
import com.qqxhb.pattern.ProductFactory;
/**
* 教室产品工厂
*
* @author Administrator
*
*/
public class ClassroomProductFactory implements ProductFactory {
@Override
public Product createTable() {
return new ClassroomTable();
}
@Override
public Product createChair() {
return new ClassroomChair();
}
}
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.AbstractChair;
/**
* 餐厅椅子
*
* @author Administrator
*
*/
public class RestaurantChair extends AbstractChair {
@Override
public void printClassify() {
System.out.println("Restaurant");
}
}
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.AbstractTable;
/**
* 餐桌
*
* @author Administrator
*
*/
public class RestaurantTable extends AbstractTable {
@Override
public void printClassify() {
System.out.println("Restaurant");
}
}
package com.qqxhb.pattern.impl;
import com.qqxhb.pattern.Product;
import com.qqxhb.pattern.ProductFactory;
/**
* 餐厅产品工厂
*
* @author Administrator
*
*/
public class RestaurantProductFactory implements ProductFactory {
@Override
public Product createTable() {
return new RestaurantTable();
}
@Override
public Product createChair() {
return new RestaurantChair();
}
}
客户端调用
package com.qqxhb.pattern;
import com.qqxhb.pattern.impl.ClassroomProductFactory;
import com.qqxhb.pattern.impl.RestaurantProductFactory;
public class Client {
public static void main(String[] args) {
/*
* 教室产品工厂生产教室课桌椅
*/
System.out.println("教室产品工厂生产教室课桌椅....");
ProductFactory classroomFactory = new ClassroomProductFactory();
Product chair = classroomFactory.createChair();
chair.printClassify();
chair.printInfo();
Product table = classroomFactory.createTable();
table.printClassify();
table.printInfo();
/*
* 餐厅产品工厂生产餐厅桌椅
*/
System.out.println("餐厅产品工厂生产餐厅桌椅....");
RestaurantProductFactory restaurantFactory = new RestaurantProductFactory();
chair = restaurantFactory.createChair();
chair.printClassify();
chair.printInfo();
table = restaurantFactory.createTable();
table.printClassify();
table.printInfo();
}
}
2. 抽象工厂模式的应用
2.1 优点
- 封装性,每个产品的实现类不是高层模块要关心的,它只关心接口和抽象,它不关心对象是如何创建出来,这由工厂类负责呢。只要知道工厂类是谁,我就能创建出一个需要的对象,省时省力,优秀设计就应该如此。
- 产品族内的约束为非公开状态。具体的产品族内的约束(如某不同分类座椅数量的比例等)是在工厂内实现的。
2.2 缺点
抽象工厂模式的最大缺点就是产品族扩展非常困难。参看示例代码,如果要增加一个产品C,也就是说产品家族由原来的2个增加到3个,抽象类ProductFactory要增加一个方法createProductC(),然后两个实现类都要修改,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。改变契约,所有与契约有关系的代码都要修改。
2.3 使用场景
抽象工厂模式的使用场景定义非常简单:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。什么意思呢?例如一个文本编辑器和一个图片处理器,都是软件实体,但是 * nix下的文本编辑器和Windows下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也有类似情况。也就是具有了共同的约束条件:操作系统类型。于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。
2.4 注意事项
在抽象工厂模式的缺点中,我们提到抽象工厂模式的产品族扩展比较困难,但是一定要清楚,是产品族扩展困难,而不是产品类别。在该模式下,产品类别是非常容易扩展的,增加一个产品类别,只要增加一个工厂类负责新增加出来的产品生产任务即可。也就是说横向扩展容易,纵向扩展困难。