定义:
Provide an interface for creating families of related or dependent
objects without specifying their concrete classes.
为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
和工厂模式一样,抽象工厂模式同样是创建型设计模式,但不同的是,抽象工厂中的每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类产品
举个栗子,你有一家公司,名下有一座生产矿泉水的工厂,它可以根据传入的订单号生产不同价位的矿泉水,这就是工厂模式,只能创建矿泉水一类产品。由于业务拓展,你想生产饮料类产品,经过协商,你建造了一个可以同时容纳矿泉水工厂和饮料工厂的超大工厂,而矿泉水工厂和饮料工厂又可以根据需求生产价位不同的饮品,这就是抽象工厂模式,抽象工厂中每个工厂可以创建多种类的产品。
下面通过RUNOOB中的例子来详细分析抽象工厂模式(简化形式,无AbstractProduct类)。
通过UML图可以很清晰的分析出抽象工厂模式的组成包括工厂生成器、抽象工厂类、工厂类、产品接口、产品接口实现类。下面通过代码分析。
代码
产品接口 – shape
public interface Shape {
void draw();
}
------------------------
public interface Color {
void fill();
}
产品接口shape实现类 – Rectangle、Square、Circle
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
--------------------------------------
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
--------------------------------------
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
产品接口color实现类 – Red 、Green 、Blue
public class Red implements Color {
@Override
public void fill() {
System.out.println("Inside Red::fill() method.");
}
}
-------------------------------------
public class Green implements Color {
@Override
public void fill() {
System.out.println("Inside Green::fill() method.");
}
}
------------------------------------
public class Blue implements Color {
@Override
public void fill() {
System.out.println("Inside Blue::fill() method.");
}
}
抽象工厂类AbstractFactory
public abstract class AbstractFactory {
public abstract Color getColor(String color);
public abstract Shape getShape(String shape);
}
来看抽象工厂类,其中定义了两个抽象方法getColor()、getShape(),接下来我们就要扩展这两个抽象方法,即创建工厂类来继承抽象工厂类,根据条件生成具体的产品。
工厂类ShapeFactory
public class ShapeFactory extends AbstractFactory {
//扩展方法,根据给定条件创建不同的产品
@Override
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
@Override
public Color getColor(String color) {
return null;
}
}
工厂类ColorFactory
public class ColorFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
return null;
}
@Override
public Color getColor(String color) {
if(color == null){
return null;
}
if(color.equalsIgnoreCase("RED")){
return new Red();
} else if(color.equalsIgnoreCase("GREEN")){
return new Green();
} else if(color.equalsIgnoreCase("BLUE")){
return new Blue();
}
return null;
}
}
工厂生成器
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("SHAPE")){
return new ShapeFactory();
} else if(choice.equalsIgnoreCase("COLOR")){
return new ColorFactory();
}
return null;
}
}
该类的作用是根据传入的条件创建具体工厂。
以上即是抽象工厂模式的大致结构,要想获取具体对象,先通过FactoryProducer类中的getFactory()获取AbstractFactory,再通过传入相应条件来获取实体类对象。
扩展:
1.在抽象工厂模式中,假设我们需要增加一个工厂(事实上是增加了产品和工厂),那该怎么做呢?
在如上代码中,假设我们要增加一个材质工厂MaterialFactory,第一步需要生成Material接口,并创建其实现类,即具体产品(Glass,Iron,Wood),第二步,在抽象工厂类中创建新的抽象方法getMaterial(),第三步,创建工厂类MaterialFactory,重写其抽象方法getMaterial(),第四步,在工厂生成器中增加判断条件。
当然若我们的结构是这样的话:即工厂类中的产品来自不同类(看UML图)
上图中,产品接口的父类是一个抽象类。
增加一个工厂(产品族)只需:
而增加一个新的产品(新的产品种类)需要:
这里修改了抽象类及其子类,违背了开闭原则。
2.它体现了设计模式中什么原则?
符合开闭原则、单一职责原则。
3.它的缺点是什么?
当增加一个新的产品种类时,此时就必须去修改抽象工厂,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。