Java对象的生产模式研究
2011-02-09王雅轩
王雅轩,顼 聪
(大连外国语学院 软件学院,大连 116044)
1 Java对象的一般生产方法
Java对象的一般生产方法是用new来创建的,以类Sample为例,如果要创建类Sample的实例对象,只要使用下面的语句即可:
Sample sample=new Sample();
但是,通常在创建类sample的实例时,要做些初始化的工作,比如赋值、查询数据库等。这好比工厂中的产品在真正出厂交付客户之前,要做一些出厂设置或配置之类的工作。这时可以使用类Sample的有参构造函数,这样生成实例就要写成:
Sample sample=new Sample(参数);
2 存在的问题
2.1 初始化工作较多时
如果创建sample实例时所做的初始化工作不是像赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,这有背于Java的面向对象的封装和分割的思想,即尽量将长的代码“切割”成每个小段,再将每个小段“封装”起来。这样,可以减少段与段之间的偶合性。以后如果需要修改,只要更改每个局部段即可,而不会对整体中的其他部分产生影响,即不会发生牵一发,而动全身的事情。
2.2 编码时不能预见需要创建哪一个类的实例时
如果一个系统中存在的类较多,而且在编码时不能预见需要创建哪一个类的实例,即需要根据一定的条件,来进行选择性地创建对象时,用一般的生产方法实现起来也比较困难。
2.3 实例的创建信息需要隐藏时
开发人员不希望创建了哪个类的实例以及如何创建实例的信息暴露给外部程序。
3 工厂模式的提出
由于上述问题,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,使创建实例所需要的大量初始化工作从类的构造函数中分离出去,因此我们提出了工厂模式,在工厂模式中,我们就可以把这些复杂的初始化工作,或选择性地生产产品的方法,或产品族的选择都可以写进工厂中。
3.1 工厂模式的分类:
1)简单工厂模式(Simple Factory)
简单工厂模式又称静态工厂方法模式[1],它把大量具有共同接口的类的实例化的过程都封装到了一个简单工厂类里了。它实现了对象的创建的过程与客户端的相互分离(即将创建对象的具体过程屏蔽隔离起来了),从而避免了客户端与产品类的直接耦合关系。
2)多型工厂模式(Factory Method)
Factory Method是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了。简单地说,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类。Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类。
3)工具箱工厂模式(Abstract Factory)
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。 抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
3.2 简单工厂模式
在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。
图1 简单工厂模式角色示意图
从图1我们可以看出简单工厂模式涉及到工厂类角色、抽象产品角色、具体产品角色三个参与者。
1) 工厂类角色Creator:工厂类在客户端的直接控制下(Create方法)创建产品对象
2)抽象产品角色Product:定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
3) 具体产品角色ConcreteProduct:定义工厂具体加工出的对象。
3.3 多型工厂模式
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给子类去作[2,3]。
图2 多型工厂模式角色示意图
从图2可以看出工厂方法模式涉及到抽象工厂角色、具体工厂角色、抽象产品角色和具体产品角色四个参与者。
1)抽象工厂角色:是工厂方法模式的核心,它负责定义创建抽象产品对象的工厂方法。抽象工厂不能被外界直接调用,但任何在模式中用于创建产品对象的工厂类都必须实现由它所定义的工厂方法。
2)具体工厂角色:是工厂方法模式的对外接口,它负责实现创建具体产品对象的内部逻辑。具体工厂与应用密切相关,可以被外界直接调用,创建所需要的产品。
3)抽象产品角色:是工厂方法模式所创建的所有对象的父类,它负责描述所有具体产品共有的公共接口。
4)具体产品角色:是工厂方法模式的创建目标,所有创建的对象都是充当这一角色的某个具体类的实例。
3.4 工具箱工厂模式
抽象工厂模式是所有形态的工厂模式中最为抽象和最具广泛性的一种形态,抽象工厂模式是工厂方法模式的进一步扩广化和抽象化。
图3 工具箱工厂模式角色示意图
如图3所示:当有多个抽象产品角色时,工厂方法模式已经不能满足要求。根据LSP里氏替换原则,任何接受父类型的地方,都应当能够接受子类型[4]。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
3.5 三种工厂模式之间的联系和区别
工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式, 把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。
反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实际工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
而在抽象工厂模式中,抽象产品可能是一个或多个,从而构成一个或多个产品族。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
4 结论
工厂方法为系统结构提供了非常灵活强大的动态扩展机制,在需要的时候,只要更换一下具体的工厂方法,系统其他地方无需任何变换,就有可能将系统功能进行改头换面的变化。
简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。
[1] Steven Metsker, William C.Wake 著,龚波,赵彩琳,陈蓓译.Java设计模式[M].北京:人民邮电出版社.2007.
[2] 阎宏.Java与模式[M]. 北京:电子工业出版社.2002.
[3] 结城浩.博硕文化译.设计模式- Java语言中的应用[M].北京: 中国铁道出版社, 2005.
[4] James W.Cooper 著.王宇,杜琪,杜志秀,译.Java与设计模式[M].北京:中国电力出版社.2003.