工厂模式是经常出现在面向对象设计中的概念。所谓工厂模式其实就是一种对象,这种的对象能返回若干可能的类以响应请求。请求数据用来确定返回哪种可能的类。在使用Java语言的情况下,返回的类应该是实现的某一接口或者某抽象类的具体实现,这样调用程序才能操作返回对象。图A所示为简单工厂模式的UML图。
图A
我们来考察下面的一个例子,这是一个数据采集应用程序,各类现场设备通过TCP/IP套接字为应用程序提供数据。最早编写应用程序的时候是设计为同一台设备通讯,但随着公司开发出新版本的硬件系统,通讯设备的功能也随之扩展。然而很不幸,新的硬件和以前的硬件版本没有操持同样的通讯语言。市场要求应用程序支持两种硬件版本,因为客户可能购买新的设备而且同旧设备一同安装。好在工厂模式减轻了支持多种设备类型的负担。
首先我们创建一个名为DataConnection的抽象类,这还是一个能正常工作的接口。于是应用程序即可同两种版本的硬件通信了。该接口用来定义连接对象不同版本的署名。然后针对每一种同应用程序具有不同通信方式的硬件版本创建专门的连接对象。就图A的例子来说,图中定义了两个对象,名字分别为Version1Connection和Version2Connection(参看程序清单A中列出的示例代码)。各自由具体的类来实现DataConnection对象定义的接口,这样程序代码就可以通过操作接口的方式操作这些连接。当然,程序清单A
中的实现只给出了说明这一概念的基本代码。
实际的工厂模式则由类ConnectionFactory实现。ConnectionFactory获得入站IP地址后返回实现DataConnection接口的对象。在这种情况下,ConnectionFactory类会在数据库中或者用其他方式查找IP地址来确定哪种硬件版本在请求通信。根据硬件的版本,
ConnectionFactory再返回适当的对象给调用代码。程序清单B列出了该工厂的实际代码。
注意,这里getConnection方法被声明为静态方法。就我们这个特殊的工厂而言,创建工厂实例没什么好处,所以该方法可以通过直接引用ConnectionFactory类的方式在代码内部被调用。在某些设计中,这样做可能有助于实例化工厂类从而建立某种缓冲机制以定位用来确定创建类的信息。
由于真实的工厂类不可能只实现一条“if”语句,所以在确定适当的类的时候有多种选择。比如说,本例中的IP地址就可以用来查询数据库,由数据库返回具有该IP地址的正确硬件版本。当然,这就需要硬件具有固定的IP地址。还有个办法是创建适当的类,用这个类保存数据库中存储的实际类名,再用Java
Class 对象的forName 和newInstance方法对适当的类实例化。
在我们的例子中工厂模式并没有完美地解决硬件多版本问题。一旦连接建立起来,你就必须处理数据采集的工作。在当前的解决方案下,每一种连接对象都得处理连接采集来的数据。但是,如果你把采集到的数据放到一组公共对象里,应用程序代码就可以处理这些数据而只把物理连接和语言细节留给连接对象了。这就意味着,采用父类来代表从硬件设备采集到的数据。为了让应用程序能够操作数据对象,应用程序就需要知道如何对适当类型的数据对象实例化。采用抽象工厂模式,返回的对象就能给应用程序提供适当的连接和数据对象。
抽象工厂模式的细节已经超出了本文所涉及的范围,不过,抽象工厂模式倒可以简单解释为“返回一组对象或者其他工厂的工厂”,如果你曾经用过Java AWT类的话,也许你就用过抽象工厂模式来建立Windows风格的应用程序GUI。
工厂模式可以让应用程序代码操作已知的父类或者接口,同时由幕后的对象来处理细节。应用程序代码之后就能够针对任务使用最优化的的对象而无需知道对象创建的细节。
欢迎评论或投稿