设计模式——抽象工厂模式(JAVA)

在抽象工厂模式中,一个具体工厂可以生产一组相关的具体产品,这样的一组产品成为产品族,产品族中的每一个产品都属于某一个产品继承等等级结构。当系统所提供的工厂生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构、属于不同类型的具体产品时就可以使用抽象工厂模式。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建,当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。

抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,而是负责创建一组产品。

抽象工厂模式定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

一、抽象工厂模式的结构

在抽象工厂模式张,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成一个产品族。

抽象工厂模式包含以下4个角色:

(1)AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。

(2)ConcreteFactory(具体工厂):它实现了抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。

(3)AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。

(4)ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,它实现抽象产品接口中声明的业务方法。

二、抽象工厂模式的实现

0_13318591595Q24.gif

在抽象工厂中声明了多个工厂方法,用于创建不同类型的产品,抽象工厂可以是接口,也可以是抽象类或具体类。

abstract class AbstractFactory

{

    public abstract AbstractProduct CreateProduct();    //工厂方法

    ......

}

具体工厂实现了抽象工厂,每一个具体的工厂方法创建一个特定的产品对象,而同一个具体工厂所创建的产品对象构成了一个产品族。对于每一个具体工厂类:

class ConcreteFactory : AbstractFactory

{

    //工厂方法

    public override AbstractProduct CreateProduct()

    {

        return new ConcreteProduct();

    }

    ......

}

与工厂方法模式一样,抽象工厂模式也可以为每一种产品提供一组重载的工厂方法,以不同的方式来创建产品对象。

三、抽象工厂模式的应用

0_1331859200u1VV.gif

在上面的类图中,两厢车和三厢车称为两个不同的等级结构;而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排量三厢车两个产品,那么这个工厂模式就是抽象工厂模式,因为他提供的产品是分属两个不同的等级结构。当然,如果一个工厂提供全部四种车型的产品,因为产品分属两个等级结构,他当然也属于抽象工厂模式了。

抽象工厂模式代码:

package AbstractFactoryModel;


interface IProduct1 {

public void show();

}

interface IProduct2{

public void show();

}

class Product1 implements IProduct1{

public void show(){

System.out.println("这是1型产品");

}

}

class Product2 implements IProduct2{

public void show(){

System.out.println("这是2型产品");

}

}

interface IFactory{

public IProduct1 createProduct1();

public IProduct2 createProduct2();

}

class Factory implements IFactory{

public IProduct1 createProduct1(){

return new Product1();

}

public IProduct2 createProduct2(){

return new Product2();

}

}


客户端代码:

package AbstractFactoryModel;


public class Client {


public static void main(String[] args) {

// TODO Auto-generated method stub

IFactory factory=new Factory();

factory.createProduct1().show();

factory.createProduct2().show();

}


}

四、抽象工厂模式的优缺点

优点:

(1)隔离了具体类的生成,使得客户端并不需要知道什么被创建。只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

(2)当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族。

(3)增加新产品族很方便,无须修改已有系统,符合开闭原则

缺点:

增加新的产品等级结构麻烦,需要对原有系统进行较大规模的修改,甚至需要修改抽象层代码,这显然会带来很大的不便,违背了开闭原则。

五、使用场景

(1)一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。

(2)系统中有多于一个的产品族,但每次只使用其中某一产品族,可以通过配置文件等方式使用户能够动态地改变产品族,也可以很方便地增加新的产品族。

(3)属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文件框,按钮和文件框之间没有直接的关系,但它们都是属于某一操作系统的。此时具有一个共同的约束条件:操作系统的类型。

(4)产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。