java设计模式之工厂模式(工厂方法)

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。
首先,在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。这个核心类则摇身一变,成为了一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
这种进一步抽象化的结果,使这种工厂方法模式可以用来允许系统在不修改具体工厂角色的情况下引进新的产品,这一特点无疑使得工厂模式具有超过简单工厂模式的优越性。
工厂方法涉及到四个角色:
1. 抽象工厂角色:工厂方法模式的核心,它是与应用程序无关的。任何在模式中创建对象的工厂类必须实现这个接口。
2. 具体工厂:它实现了抽象工厂角色的所有接口,主要负责创建产口对象。
3. 抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。这个角色由Java 接口Product 扮演;在实际的系统中,这个角色也常常使用抽象Java 类实现(比如单例模式中等等)。
4. 具体产品:实现了抽象产品角色所有的接口。工厂方法中创建每一个对象都是某个产品角色具体的实例。
如下图所示:

图5.1.2_1 工厂方法示例图
由上图可知分别对应的四个角色:Creator充当了抽象工厂的角色;ConcreteCreator1和ConcreteCreator2充当了具体的工厂;Product充当抽象产品角色;ConcreteProduct1和ConcreteProduct2表示具体的产品对象。上面正好表现了它们之间的关系。
代码如下:
/***创建抽象工厂角色***/
public interface Creator
{
public Product factory();
}
 
/***创建产品角色****/
public interface Product
{}
 
/***创建ConcreteCreator1 工厂****/
public class ConcreteCreator1 implements Creator
{
public Product factory()
{
return new ConcreteProduct1();
}
}
 
/***创建ConcreteCreator2 工厂****/
public class ConcreteCreator2 implements Creator
{
public Product factory()
{
return new ConcreteProduct2();
}
}
 
/***创建ConcreteProduct1产品****/
public class ConcreteProduct1 implements Product
{
public ConcreteProduct1()
{
//do something
}
}
 
/***创建ConcreteProduc2产品****/
public class ConcreteProduct2 implements Product
{
public ConcreteProduct2()
{
//do something
}
}
 
 
客户端创建ConcreteCreator1 对象。这时客户端所持有变量的静态类型是Creator,而实际类型是ConcreteCreator1。然后,客户端调用ConcreteCreator1 对象的工厂方法factory(),接着后者调用ConcreteProduct1 的构造子创建出产品对象。
 
/***客户端代码****/
public class Client
{
private static Creator creator1, creator2;
private static Product prod1, prod2;
public static void main(String[] args)
{
creator1 = new ConcreteCreator1();
prod1 = creator1.factory();
creator2 = new ConcreteCreator2();
prod2 = creator2.factory();
}
}
 
  工厂方法模式和简单工厂模式在结构上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式( 创建型类模式将对象的部分创建工作延迟到子类)。
工厂方法模式退化后可以变得很像简单工厂模式。设想如果非常确定一个系统只需要一个具体工厂类,那么就不妨把抽象工厂类合并到具体的工厂类中去。由于反正只有一个具体工厂类,所以不妨将工厂方法改成为静态方法,这时候就得到了简单工厂模式。
与简单工厂模式中的情形一样的是, ConcreteCreator factory() 方法返还的数据类型
是一个抽象类型 Product ,而不是哪一个具体产品类型,而客户端也不必知道所得到的产品
的真实类型。这种多态性设计将工厂类选择创建哪一个产品对象、如何创建这个对象的细
节完全封装在具体工厂类内部。
工厂方法模式之所以有一个别名叫多态性工厂模式,显然是因为具体工厂类都有共同
的接口,或者都有共同的抽象父类。
如果系统需要加入一个新的产品,那么所需要的就是向系统中加入一个这个产品类以及它所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的产品类而言,这个系统完全支持“开-闭”原则。
我们对简单工厂方法中的例子再进一步说明:
图5.1.2_1 工厂方法示例图
 
根据上图的例子,我们很容易得出代码:
 
/**抽象工厂角色**/
public interface FruitGardener
{
   public Fruit facory();
}
 
/** 具体工厂 1*/
public AppleGardener implements FruitGardener
{
public Fruit facory()
{
    return new Apple();
}
}
 
/** 具体工厂 2/
public GrapeGardener implements FruitGardener
{
public Fruit facory()
{
    return new Grape ();
}
}
 
/** 抽象产品角色 **/
pulbic interface Fruit
{
   public void grow();
public void harvest();
public void plant();
}
 
/** 具体产品 1**/
public class Apple implements Fruit
{
private int treeAge;
public Apple(){};
public void grow()
{
System.out.println("Apple is growing...");
}
public void harvest()
{
System.out.println("Apple has been harvested.");
}
public void plant()
{
System.out.println("Apple has been planted.");
}
public int getTreeAge()
{
return treeAge;
}
public void setTreeAge(int treeAge)
{
this.treeAge = treeAge;
}
}
 
/** 具体产品 2**/
public class Grape implements Fruit
{
private boolean seedless;
public void grow()
{
System.out.println("Grape is growing...");
}
public void harvest()
{
System.out.println("Grape has been harvested.");
}
public void plant()
{
System.out.println("Grape has been planted.");
}
public boolean getSeedless()
{
return seedless;
}
public void setSeedless(boolean seedless)
{
this.seedless = seedless;
}
}
 
由此我们完成了基于工厂方法的基本结构。客户端可利用下面代表,调试:
 
 
/**客户端**/
public class client
{
private static FruitGardener creator1, creator2;
private static Fruit  prod1, prod2;
  pulbic client()
{}
public static void main(String[] args)
{
  creator1 = new AppleGardener();
  prod1 = creator1. facory();
  creator2 = new GradeGardener();
  prod1 = creator1. facory();
}
}
 
注:在实际应用中,工厂方法所从事的工作是相当复杂的,比如,循环使用产品对象,并且产品对象具有其内部的特征。针对这种情况工厂对象就需要将已经创建过的产品对象登记到一个聚集里面,然后根据客户端所请求的产品状态,向聚集进行查询。如果聚集中有这样的产品对象,那么就直接将这个产品对象返还给客户端;如果聚集中没有这样的产品对象,那么就创建一个新的满足要求的产品对象,然后将这个对象登记到聚集中,再返还给客户端。
关于这一点, 享元模式已提供了对此的解决方案,至于解决办法,我们在后面会有所讨论,大家先别急。
 
工厂方法特点总结
工厂方法返回的对象,一定是它亲自创建的对象;工厂方法所返还的应当是抽象类型,而不是具体类型,只有这样才能保证针对产品的多态性。然而,在特殊情况下,工厂方法仅仅返还一个具体产品类型。在出现这种情况下,我们可以认为工厂方法模式的功能就退化了,表现为针对产品角色的多态性的丧失。换言之,客户端从工厂方法的静态类型可以得知将要得到的是什么类型的对象,而这违背了工厂方法模式的用意。
 
工厂方法与其它模式之间的关系
   1. 模板方法模式: 工厂方法模式将创建工作推延给子类,模板方法模式将剩余逻辑交给子类。从各个工厂角色组成的工厂等级结构上看,抽象工厂角色中可以加入一个模板方法,代表某个顶级逻辑。而这个模板方法调用几个基本方法,这些基本方法中就可以有一个或者多个是工厂方法。这些工厂方法代表剩余逻辑,交给具体子类实现。
模版方法本身也可能是工厂方法,它的对象创建过程就是所谓的顶级结构;而这个过程可以分为数个具体步骤,每一个步骤都是顶级逻辑的组成部分。换言之,使用模板方法模式可以将某一个顶级行为分解成为数个创建行为,由子类中的工厂方法体现出来。不同的具体工厂类则提供了顶级逻辑中的剩余逻辑的不同实现。通过使用不同的具体工厂对象,客户端可以达到使用不同版本的顶级逻辑的目的。
2. MVC 模式:工厂方法模式总是涉及到两个等级结构中的对象(如抽象工厂和抽象产品),而这两个等级结构可以分别是MVC模式中的控制器(Controller)和视图(View)。一个MVC 模式可以有多个控制器和多个视图。换言之,控制器端可以创建合适的视图端,就如同工厂角色创建合适的对象角色一样,模型端则可以充当这个创建过程的客户端。
3. 享元模式:后面会有介绍
4. 备忘录模式:后面会有介绍
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值