sourcemaking.com
目的:
- 提供一个接口来创建相关的或有依赖的对象们的家庭,而不用指明他们的具体类。
- 一种层级结构封装了:许多可能的“平台”(比如窗口系统、操作系统、数据库等),还有构建了一套“产品”。
- new 操作在这里认为是有害的。
问题:
如果一个应用被认为是便携式的,它需要封装平台依赖。这些平台可能包括窗口系统、操作系统、数据库等。经常,这种封装并没有在之前就设计出来,并且代码中有非常多if判断来配置不同的支持平台,就像生产兔子一样。
讨论:
提供一个间接层来抽象化相关联的或者有依赖关系的一类对象的创建,而不用具体化类。这个“工厂”对象有责任提供整个平台家庭的创建相关服务。客户端从来不用直接创建平台对象,他们让工厂帮他们创建。
这种机制使得交换产品家庭变得简单,因为具体的工厂对象类只有在实例化的时候出来一次。应用可以批发式的更换整个产品家庭简单的通过实例化一个不同的抽象工厂。
因为工厂对象提供的服务无处不在,所以通常被实现成单例(Singleton)模式。
结构:
抽象工厂在每一个产品里定义了一个工厂方法。每一个工厂方法封装了new操作和具体的、平台细化的产品类们。然后每一个”平台“通过一个工厂衍生出来的类被模具化出来。
例子:
抽象工厂的目的是为了提供一个接口来创建相关对象的家庭而不用指明具体类。这种模式被用在日本汽车的片状金属冲压装置上。冲压装置是一个抽象工厂,它制造汽车车身部件。同样的机器被用来冲压右车门、左车门、左前挡泥板、右前挡泥板、车顶等等,给不同的车型。通过不同的滚压机改变冲压钢型,机器生产的具体的类可以在三分钟内改变。
核对表:
- 判断是否是“平台独立的”并且建立服务是当前痛苦来源。
- 列一个平台对产品的矩阵。
- 定义一个工厂接口包括每个产品一个工厂方法。
- 为每一个平台定义一个工厂衍生类,它封装了所有对new操作的引用。
- 客户端应该淘汰所有对new的引用,改为用工厂方法建立产品对象。
经验法则:
- 有时候Creational Patterns (创建模式)存在竞争关系:有这种情况不管是Prototype、Abstract Factory都可以被有益的使用。还有时他们可以是互补的:抽象工厂可能存一系列的Prototypes来克隆然后返回产品对象,Builder模式可以用另一个模式来实现哪一个组件被建立。Abstract Factory、Builder和Prototype实现时都可以用到Singleton。
- Abstract Factory、Builder和Prototype定义了一个工厂对象它有责任了解建造产品对象的类,并且把它作为系统的一个参数。抽象工厂有一个工厂对象生产好几种类的对象。Builder有一个工厂对象用一种相对复杂的协议渐渐地建立一个复杂的产品。Prototype有一个工厂对象(aka prototype)通过复制一个prototype对象来建立一个产品。
- 抽象工厂类通常通过工厂方法实现,但也可以通过prototype实现。
- 抽象工厂可以备用来作为Facade的替代,来隐藏具体平台的类。
- Builder关注在一步一步的建立一个复杂的对象。抽象工厂则是注重于一个家庭的产品对象(简单或复杂)。Builder最后一步才返回产品,而只要抽象工厂被提到,产品就立马返回。
- 通常设计从工厂方法(没那么复杂、更多的可定制性、生产子类)开始,然后指向抽象工厂、prototype或者Builder(更灵活、更复杂)当设计者发现需要更灵活的地方。
Java示例代码一:
抽象工厂类通常是通过工厂方法实现的,但是它也可以通过Prototype模式实现。抽象工厂可以存储Prototypes的集合然后从它进行克隆和返回产品对象。
- 工厂方法:通过集成创建。
- Prototype(雏形?):通过delegation(委派?)创建。
- 虚拟构造函数:直到运行时才选择创建的对象。
public class FactoryFmProto
{
static class Expression
{
protected String str;
public Expression(String s)
{
str = s;
}
public Expression cloan()
{
return null;
}
public String toString()
{
return str;
}
}
static abstract class Factory
{
protected Expression prototype = null;
public Expression makePhrase()
{
return prototype.cloan();
}
public abstract Expression makeCompromise();
public abstract Expression makeGrade();
}
static class PCFactory extends Factory
{
public PCFactory()
{
prototype = new PCPhrase();
}
public Expression makeCompromise()
{
return new Expression("\"do it your way, any way, or no way\"");
}
public Expression makeGrade()
{
return new Expression("\"you pass, self-esteem intact\"");
}
}
static class NotPCFactory extends Factory
{
public NotPCFactory()
{
prototype = new NotPCPhrase();
}
public Expression makeCompromise()
{
return new Expression("\"my way, or the highway\"");
}
public Expression makeGrade()
{
return new Expression("\"take test, deal with the results\"");
}
}
public static void main(String[] args)
{
Factory factory;
if (args.length > 0)
factory = new PCFactory();
else
factory = new NotPCFactory();
for (int i = 0; i < 3; i++)
System.out.print(factory.makePhrase() + " ");
System.out.println();
System.out.println(factory.makeCompromise());
System.out.println(factory.makeGrade());
}
static class PCPhrase extends Expression
{
static String[] list =
{
"\"animal companion\"", "\"vertically challenged\"",
"\"factually inaccurate\"", "\"chronologically gifted\""
};
private static int next = 0;
public PCPhrase()
{
super(list[next]);
next = (next + 1) % list.length;
}
public Expression cloan()
{
return new PCPhrase();
}
}
static class NotPCPhrase extends Expression
{
private static String[] list =
{
"\"pet\"", "\"short\"", "\"lie\"", "\"old\""
};
private static int next = 0;
public NotPCPhrase()
{
super(list[next]);
next = (next + 1) % list.length;
}
public Expression cloan()
{
return new NotPCPhrase();
}
}
}
运行结果:
D:\Java\patterns> java FactoryFmProto
"short" "lie" "old"
"my way, or the highway"
"take test, deal with the results"
D:\Java\patterns> java FactoryFmProto 1
"vertically challenged" "factually inaccurate" "chronologically gifted"
"do it your way, any way, or no way"
"you pass, self-esteem intact"
Java示例代码二:
public abstract class CPU
{
...
} // class CPU
class EmberCPU extends CPU
{
...
} // class EmberCPU
class EmberToolkit extends ArchitectureToolkit
{
public CPU createCPU()
{
return new EmberCPU();
} // createCPU()
public MMU createMMU()
{
return new EmberMMU();
} // createMMU()
...
} // class EmberFactory
public abstract class ArchitectureToolkit
{
private static final EmberToolkit emberToolkit = new EmberToolkit();
private static final EnginolaToolkit enginolaToolkit = new EnginolaToolkit();
...
// Returns a concrete factory object that is an instance of the
// concrete factory class appropriate for the given architecture.
static final ArchitectureToolkit getFactory(int architecture)
{
switch (architecture)
{
case ENGINOLA:
return enginolaToolkit;
case EMBER:
return emberToolkit;
...
} // switch
String errMsg = Integer.toString(architecture);
throw new IllegalArgumentException(errMsg);
} // getFactory()
public abstract CPU createCPU();
public abstract MMU createMMU();
...
} // AbstractFactory
public class Client
{
public void doIt()
{
AbstractFactory af;
af = AbstractFactory.getFactory(AbstractFactory.EMBER);
CPU cpu = af.createCPU();
...
} // doIt
} // class Client
另外可以参考自己写的一个例子:
http://blog.csdn.net/xiaobaiooo/article/details/44062599