设计模式是经验总结,是学习软件设计的有效方法,因此,了解和理解现有的设计模式,是提高软件设计的有效途径之一,这里将介绍相关的设计模式,并通过示例了理解其用法。
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。
抽象工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。
意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决: 主要解决接口选择的问题。
何时使用: 系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决: 在一个产品族里面,定义多个产品。
关键代码: 在一个工厂里聚合多个同类产品。
应用实例: 工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点: 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点: 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项: 产品族难扩展,产品等级易扩展。
示例
这里以产品的生产和包装为例,来说明如何使用抽象工厂模式。
现在要配套生产两个系列的螺钉和螺母,分别是M6和M10,完成生产后进行装箱,以便于运输,这是基本的设计思路,下面来看看具体实现。
和工厂方法模式类似,要生产M6和M10的螺钉和螺母,想要进行抽象,通过接口的实现来表明对应的产品,先来看看螺钉的接口,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
//螺钉
public interface IScrew {
public void print();
}
有了螺钉的接口,就可以实现M6螺钉了,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class ScrewM6 implements IScrew {
@Override
public void print() {
System.out.println("6mm螺纹螺钉");
}
}
M10的螺钉的代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class ScrewM10 implements IScrew {
@Override
public void print() {
System.out.println("10mm螺纹螺钉");
}
}
类似地,可以产生对应的螺母类,螺母接口代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public interface INut {
public void print();
}
M6的螺母的代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class NutM6 implements INut {
@Override
public void print() {
System.out.println("6mm螺纹螺母");
}
}
M10的螺母的代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class NutM10 implements INut {
@Override
public void print() {
System.out.println("10mm螺纹螺母");
}
}
有了这些产品,就可以通过工厂来生产这些产品了,同样地,定义一个工厂接口,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public interface IAbstractFactory {
public IScrew makeScrew();
public INut makeNut();
}
工厂中提供生产产品的方法,即工厂方法,为了完成有针对性的生产,就需要产生M6和M10的螺钉和螺纹的生产工厂,即M6的工厂生产M6的螺钉和螺纹,M10的工厂生产M10的螺钉和螺纹,那么,M6的工厂代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class ConcreteFactoryM6 implements IAbstractFactory {
@Override
public IScrew makeScrew() {
return new ScrewM6();
}
@Override
public INut makeNut() {
return new NutM6();
}
}
M10的工厂代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class ConcreteFactoryM10 implements IAbstractFactory {
@Override
public IScrew makeScrew() {
return new ScrewM10();
}
@Override
public INut makeNut() {
return new NutM10();
}
}
有了工厂,能够生产出系列产品,还需要对产品进行装箱,即将产品放入包装箱中,显示包装箱的清单,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class PackingCase {
private int amount;
private int numberOfScrew = 0;
private int numberOfNut = 0;
private IScrew[] screws;
private INut[] nuts;
public PackingCase(int amount) {
this.amount = amount;
screws = new IScrew[amount];
nuts = new INut[amount];
}
int amount() {
return amount;
}
public void putTheScrewsIn(IScrew screw) {
if (numberOfScrew == amount) {
return;
} else {
numberOfScrew++;
screws[numberOfScrew - 1] = screw;
}
}
public void putTheNutIn(INut nut) {
if (numberOfNut == amount) {
return;
} else {
numberOfNut++;
nuts[numberOfNut - 1] = nut;
}
}
public void showDetail() {
int i;
for (i = 0; i < numberOfScrew; i++) {
screws[i].print();
}
for (i = 0; i < numberOfNut; i++) {
nuts[i].print();
}
}
}
现在,可以进行产品生产和装箱,那么,需要这样的动作能够集成到一起,自动完成生产和装箱过程,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
public class ProductionMachine {
private IAbstractFactory factory = null;
public void setFactory(IAbstractFactory factory) {
this.factory = factory;
}
public void packing(PackingCase packingCase) {
int i;
for (i = 0; i <= packingCase.amount(); i++) {
packingCase.putTheScrewsIn(factory.makeScrew());
packingCase.putTheNutIn(factory.makeNut());
}
}
}
这样,就可以进行产品的生产和装箱了,在使用时,直接指定装箱规格即可,代码如下:
package cn.lut.curiezhang.designpattern.abstractfactory;
/**
* Client
*
*/
public class Client
{
static ProductionMachine machine = new ProductionMachine();
static PackingCase packingCase1 = new PackingCase(5);
static PackingCase packingCase2 = new PackingCase(3);
public static void main( String[] args )
{
machine.setFactory(new ConcreteFactoryM6());
machine.packing(packingCase1);
packingCase1.showDetail();
System.out.println();
machine.setFactory(new ConcreteFactoryM10());
machine.packing(packingCase2);
packingCase2.showDetail();
}
}
代码执行结果如下图所示:
代码实现就是这样的,下面来看看上面设计模式的基本结构,通过类图了解其基本构成,如下图所示:
了解了其基本结构,就需要搞清楚这些类是怎么样来完成交互的,也就是这些对象之间是如何协作的?就通过顺序图来了解其工作过程,如下图所示:
请注意其交互过程。