您的位置:首页 > 编程语言 > Java开发

创建型模式之一 工厂模式(Java实现)(一)

2006-10-22 21:04 465 查看
------------------------------创建型模式之一-------工厂模式(Java实现)(一)-------------------------
一、简介:
我们不妨把工厂模式分成以下三种:
1) 简单工厂:不要求产品之间有等级关系,甚至是可以使一些不相关的产品(我们知道所有的类都有公共的基类Object,这点共同点就足够了),我们不妨称之为“杂货工厂”。虽然说是简单工厂,但是它的创造的产品确是丰富多彩的。加上 java的反射功能我们我们甚至可以创建万事万物------万事皆是对象。像java.text.DataFormat,就是一个Data的简单工厂,用来格式化并产生本地的Data.
2) 工厂方法:工厂方法又称为虚拟构造子。要求产品之间有等级关系。构造函数固有的特点,使它不能被继承,当然更不能使用多态来动态的灵活的创建实例,这往往会使程序中到处充满硬编码的new,当我们的需要变更时,我们不得不更改大量的new语句来适应需求。有时我们也会遇到这种情况:我们要实例化一个类的子类,而这个类与具体应用相关,这时我们不可能知道要实例化哪个子类。我们的工厂方法给我们提供了虚拟的构造子,它使一个类的实例化延迟到其子类。其实简单工厂也被称为一种工厂方法,只是我们是通过参数来传递我们要创建的的信息,从来决定要创建的产品,在GOF的《设计模式》中被成为参数化的工厂方法。但二者实现及应用场景不同,我们不妨分开来说并加以比较。
3) 抽象工厂:抽象工厂往往与多个产品系列的创建有关,并且要求产品之间有等级关系。举个生活中的例子来说,许多电脑厂商都生产系列机,所谓的系列机是指体系结构相同的档次不同的机器。我们不妨假设不同的系列机的部件是不兼容的。这可能是抽象工厂的最佳使用时机,他的优点是:i)有利于产品的的一致性,从而不会产生不同系列产品的不兼容,因为我们使用一个工厂只会生产一系列的产品。ii)容易交换不同系列的产品-----只需要更换掉工厂即可。
以上是工厂模式的一个简介,下面我们将分别介绍:
二)简单工厂:
简单工厂其实就是根据参数来决定要创建的类,说是简单,其实他常常被用来创建强大的功能。像现在比较流行的IOC(Inversion of Control),其实就是让程序员从繁杂的对象的创建中解脱出来,与以前相比让角色反转,让容器来负责类的实例化,这与java 的垃圾回收机制有着异曲同工之妙,都是让一切简化。其实现思想其实很简单,就是一个很大的工厂,一个工程中的所有的对象都可以从中取,该工厂从.xml配置文件中读取要实例化的类的信息及其对象间的依赖关系,并将这些依赖关系注入到对象中,Bean factory给我们创建和管理bean,不仅可以减轻我们的负担,更重要的是产生了松耦合的系统。
类似如下:
class BeanFactory{
static Object getBean(String className){
return Class.forName(className).newInstance();
}
//…从xml中读去配置信息来实例化各个对象
}
以后的步骤基本上是:从.xml文件中读去Bean的信息,提取出bean的名字beanName这样调用一下XxxBean bean = BeanFactory.getBean(beanName)就得到想要的 bean了;当然这只是简单的说,考虑到灵活性还需要许多的模式一起来完成。
其实简单工厂的主要优点就是分离了产品与产品的创建,用户只需要与工厂打交道,而不必与具体的产品打交道。像Spring中提供的BeanFactory,被称为Bean的Container,用户只需要从BeanFactoy中得到所需要的bean,而不需要关注如何创建,之所以是 Container 是因为BeanFactory会缓存这些bean,但是在开始的出于性能的考虑,不会一下子产生所有的bean,而是采用lazy load方式.当你把bean设置为Singleton的时候,BeanFactory会始终返那个缓存的实例,而不真正创建。
象我以前写的那个SNLCompiler就使用了这个模式,实现如下:
public ActionFactory{
Action []actionCache = new Action[]{
new Action1(),new Action2(),
//…
new Action106()
}

public Action create ActionInstance(int i){
return actionCache[i];
}
}
actionCache 是Action的缓存,每个Action 都是一个采用Command的模式的一个动作,由于这些Action都是无状态的(没有数据成员),性能不会受到影响,并且由于缓存作用而使
这些实例能够预先创建并且得到共享,当然这只是附带的性能上好处。我在使用这个模式的主要目的是:提供一个数字与一个动作的映射。如果从SNLCompiler的背景中来说,就是从LL(1)文法的动作表中(一个非终极符和输入token流的匹配表,表中填写使用的匹配的文法的序号),找到对应的文法序号,并且每条文法对应一个处理动作(Action)。从而根据找到的文法序号来产生对应的Action,然后使用多态来处理不同的文法:
Action action = factory.createActionInstance(num);
predict(action);
从而避免在predict中使用庞大的 switch…case的判断。

以上举的是实际中遇到的例子,为了便于理解,我们也写一个被人称为“玩具”一样的例子。
举个水果加工场的例子吧:
//FuitFactory水果工厂类:
public class FruitFactory{
public Fruit createFruit(String fruitName){
if(fruitName .equals(“apple”)){
return new Apple();
}else if(fruitName.equals(“pear”)){
return new Pear();
}else if(fruitName.equals(“banana”)){
return new Banana();
}
}
}

public interface Fruit{
//…
}

public class Apple implements Fruit{
public Apple(){
}
//…
}

public class Pear implements Fruit{
public Pear (){
}
//…
}

public class Banana implements Fruit{
public Banana (){
}
//…
}

public class Test{
public static void main(String []args){
FruitFactory factory = new FruitFactory();
Apple apple = (Apple)factory.createFruit(“apple”);
//…
}
}
上面的实现有个缺点,就是当产品增加时需要修改Factory。当然你可以使用java的反射来动态的事例化类(Class.forName(classname).newInstace()),来克服。
待续 之二 ---------Factory Method
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐