工厂模式细分有三种,分别为:简单工厂模式、工厂方法模式、抽象工厂模式。
通过一个农场的实例来讲解,例子如下:
有一个农场公司,专门向市场销售各类水果有如下水果:
葡萄(grape)
草莓(strawberry)
苹果(apple)
简单工厂模式:
简单工厂模式又称静态工厂方法模式。它存在的目的很简单:定义一个用于创建对象的接口。
在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定哪一个产品类应当被实例化,
如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。
组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
在java中它往往由一个具体类实现(FruitGardener)。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
在java中由接口或者抽象类来实现(Fruit)。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。
在java中由一个具体类实现(Apple等)。
源代码如下:
Fruit.java:
public interface Fruit
{
void grow();
void harvest();
void plant();
}
下面是Apple类的函数
Apple.java:
public class Apple implements Fruit
{
private int treeAge;
public void grow() {
//苹果的生长函数代码
}
public void harvest() {
//苹果的收获函数代码
}
public void plant() {
//苹果的种植函数代码
}
public int getTreeAge() {
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
下面是Grape类的函数Grape.java:
public class Grape implements Fruit
{
private boolean seedless;
public void grow() {
//葡萄的生长函数代码
}
public void harvest() {
//葡萄的收获函数代码
}
public void plant() {
//葡萄的种植函数代码
}
public boolean getSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
下面是Strawberry类的函数
Strawberry.java:
public class Strawberry implements Fruit
{
private boolean coteless;
public void grow() {
//草莓的生长函数代码
}
public void harvest() {
//草莓的收获函数代码
}
public void plant() {
//草莓的种植函数代码
}
public boolean getCoteless() {
return coteless;
}
public void setCoteless(boolean coteless) {
this. coteless = coteless;
}
}
农场的园丁也是系统的一部分,我们用FruitGardener类来表示
FruitGardener类会根据客户端的要求,创建出不同的水果对象,比如苹果(apple),
葡萄(grape)或草莓(strawberry)的实例代码如下所示:
FruitGardener.java:
public class FruitGardener
{
public static Fruit factory(String which) throws BadFruitException
{
if (which.equalsIgnoreCase("apple")) {
return new Apple();
}else if (which.equalsIgnoreCase("strawberry")) {
return new Strawberry();
}else if (which.equalsIgnoreCase("grape")) {
return new Grape();
}else {
throw new BadFruitException("Bad fruit request");
}
}
}
简单工厂方法
优点:当在系统中引入新产品时不必修改客户端。
缺点:需要个修改工厂类,将必要的逻辑加入到工厂类中
工厂方法模式就克服了以上缺点,下面谈谈工厂方法模式
工厂方法模式:
组成:
1)抽象工厂角色:工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者
必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。
在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。可以看出工厂角色的结构也是符合开闭原则的
Fruit.java:
public interface Fruit
{
void grow();
void harvest();
void plant();
}
Apple.java:
public class Apple implements Fruit
{
private int treeAge;
public void grow() {
//苹果的生长函数代码
}
public void harvest() {
//苹果的收获函数代码
}
public void plant() {
//苹果的种植函数代码
}
public int getTreeAge() {
return treeAge;
}
public void setTreeAge(int treeAge) {
this.treeAge = treeAge;
}
}
Grape.java:
public class Grape implements Fruit
{
private boolean seedless;
public void grow() {
//葡萄的生长函数代码
}
public void harvest() {
//葡萄的收获函数代码
}
public void plant() {
//葡萄的种植函数代码
}
public boolean getSeedless() {
return seedless;
}
public void setSeedless(boolean seedless) {
this.seedless = seedless;
}
}
Strawberry.java:
public class Strawberry implements Fruit
{
private boolean coteless;
public void grow() {
//草莓的生长函数代码
}
public void harvest() {
//草莓的收获函数代码
}
public void plant() {
//草莓的种植函数代码
}
public boolean getCoteless() {
return coteless;
}
public void setCoteless(boolean coteless) {
this. coteless = coteless;
}
}
下面的源码就是工厂方法模式的重点了,在简单工厂模式中,将这里将FruitGardener定
义为一个类,即园丁要管理园里的所有水果,如果园丁哪天病了,水果都不能管理了
在工厂方法模式中将FruitGardener定义为一个接口,而将管理水果的角色划分得更细,
比如有葡萄园丁、草莓园丁、苹果园丁等等具体角色。
实现FruitGardener接口的工厂方法源码如下所示:
接口FruitGardener的源码:
public interface FruitGardener
{
Fruit factory();
}
苹果园丁类AppleGardener.java的源码:
public class AppleGardener implements FruitGardener
{
public Fruit factory() {
return new Apple();
}
}
葡萄园丁类GrapeGardener.java的源码:
public class GrapeGardener implements FruitGardener
{
public Fruit factory() {
return new Grape();
}
}
草莓园丁类StrawberryGardener.java的源码:
public class StrawberryGardener implements FruitGardener
{
public Fruit factory() {
return new Strawberry();
}
}
由以上源码可以看出,使用工厂方法模式保持了简单工厂模式的优点,克服了其缺点
当在系统中引入新产品时,既不必修改客户端,又不必修改具体工厂角色可以较好
的对系统进行扩展
同时可以看出工厂方法的加入,使得对象的数量成倍增长。当产品种类非常多时,
会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,
可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类
(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
工厂方法模式和简单工厂模式在定义上的不同是很明显的。
工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式,把核心放在一个实类上。
工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。
反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
抽象工厂模式:
现在工厂再次大发展,要引进塑料大棚技术,在大棚里种植热带(Tropical)和亚热带的
水果和蔬菜(Veggie)其中水果分为TropicalFruit和NorthernFruit,蔬菜分为TropicalVeggie
和NorthernVeggie,园丁包括TropicalGardener和NorthernGardener,也就是说,
TropicalGardener专门管理TropicalFruit和TropicalGardener,NorthernGardener专门
管理NorthernFruit和NorthernVeggie。抽象工厂模式在这个例子中的源码如下所示:
Fruit.java:
public interface Fruit {
}
NorthernFruit.java:
public class NorthernFruit implements Fruit
{
private String name;
public NorthernFruit(String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
TropicalFruit.java:
public class TropicalFruit implements Fruit
{
private String name;
public TropicalFruit(String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Veggie.java:
public interface Veggie {
}
TropicalVeggie.java:
public class TropicalVeggie implements Veggie
{
private String name;
public TropicalVeggie(String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
NorthernVeggie.java:
public class NorthernVeggie implements Veggie
{
private String name;
public NorthernVeggie(String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Gardener.java:
public interface Gardener
{
Fruit createFruit(String name);
Veggie createVeggie(String name);
}
TropicalGardener.java:
public class TropicalGardener implements Gardener
{
public Fruit createFruit(String name) {
return new TropicalFruit(name);
}
public Veggie createVeggie(String name) {
return new TropicalVeggie(name);
}
}
NorthernGardener.java:
public class NorthernGardener implements Gardener
{
public Fruit createFruit(String name) {
return new NorthernFruit(name);
}
public Veggie createVeggie(String name) {
return new NorthernVeggie(name);
}
}
为了简单起见,这里只讲一下增加新产品(族)时该系统如何扩展,
比如现在要增加南方水果(SouthFruit)和南方蔬菜(SouthVeggie)那
么只要增加如下代码即可很容易的扩展:
SouthFruit.java:
public class SouthFruit implements Fruit
{
private String name;
public SouthFruit (String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SouthVeggie.java:
public class SouthVeggie implements Veggie
{
private String name;
public SouthVeggie (String name) {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
SouthGardener.java:
public class SouthGardener implements Gardener
{
public Fruit createFruit(String name) {
return new SouthFruit(name);
}
public Veggie createVeggie(String name) {
return new SouthVeggie(name);
}
}
在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而
构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
工厂模式在《Java与模式》中分为三类:
1) 简单工厂模式(Simple Factory):不利于产生系列产品;
2) 工厂方法模式(Factory Method):又称为多形性工厂;
3) 抽象工厂模式(Abstract Factory):又称为工具箱,产生产品族,但不利于产生新的产品;
这三种模式从上到下逐步抽象,并且更具一般性。
GOF在《设计模式》一书中将工厂模式分为两类:
工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。
将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
(1)简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
(2)工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
(3)抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。
参考:http://blog.163.com/tangyang_personal/blog/static/46229613200861053256844/
http://www.cnblogs.com/forlina/archive/2011/06/21/2086114.html