FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化
举个例子:
首先定义一个抽象类Shape,定义两个抽象的方法.
abstract class Shape {
public String name; public Shape(String aName){ name = aName; } // 勾画shape public abstract void draw(); // 擦去 shape public abstract void erase(); }
|
定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法
// 圆形子类
class Circle extends Shape { public void draw() { System.out.println("It will draw a circle."); } public void erase() { System.out.println("It will erase a circle."); } // 构造函数 public Circle(String aName){ super(aName); } } // 方形子类
class Square extends Shape { public void draw() { System.out.println("It will draw a square."); } public void erase() { System.out.println("It will erase a square."); } // 构造函数 public Square(String aName){ super(aName); } }
|
定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.
abstract class ShapeFactory { protected abstract Shape factoryMethod(String aName); // 在anOperation中定义Shape的一系列行为 public void anOperation(String aName){ Shape s = factoryMethod(aName); System.out.println("The current shape is: " + s.name); s.draw(); s.erase(); } }
|
定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法
// 定义返回 circle 实例的 CircleFactory
class CircleFactory extends ShapeFactory { // 重载factoryMethod方法,返回Circle对象
protected Shape factoryMethod(String aName) { return new Circle(aName + " (created by CircleFactory)"); } } // 定义返回 Square 实例的 SquareFactory
class SquareFactory extends ShapeFactory { // 重载factoryMethod方法,返回Square对象
protected Shape factoryMethod(String aName) { return new Square(aName + " (created by SquareFactory)"); } }
|
客户端函数:
class Main { public static void main(String[] args){ ShapeFactory sf1 = new SquareFactory(); ShapeFactory sf2 = new CircleFactory(); sf1.anOperation("Shape one"); sf2.anOperation("Shape two"); } }
|
参数化的Factory Method: 这种方式依靠指定的参数作为标志来创建对应的实例,这是很常见的一种办法.比如JFC中的BorderFactory就是个很不错的例子. 以下的这个例子是用字符串作为标记来进行判断的,如果参数的类型也不一样,那就可以用到过载函数来解决这个问题,定义一系列参数和方法体不同的同名函数,这里java.util.Calendar.getInstance()又是个极好的例子.参数化的创建方式克服了Factory Method模式一个最显著的缺陷,就是当具体产品比较多时,我们不得不也建立一系列与之对应的具体构造器. 但是在客户端我们必须指定参数来决定要创建哪一个类.
我们在第一种方法的基础上进行修改,首先自定义一个的异常,这样当传入不正确的参数时可以得到更明显的报错信息.
class NoThisShape extends Exception { public NoThisShape(String aName) { super(aName); } }
|
去掉了ShapeFactory的两个子类,改为由ShapeFactory直接负责实例的创建. ShapeFactory自己变成一个具体的创建器,直接用参数化的方法实现factoryMethod返回多种对象.
abstract class ShapeFactory { private static Shape s; private ShapeFactory() {} static Shape factoryMethod(String aName, String aType) throws NoThisShape{ if (aType.compareTo("square")==0) return new Square(aName); else if (aType.compareTo("circle")==0) return new Circle(aName); else throw new NoThisShape(aType); } // 在anOperation中定义Shape的一系列行为
static void anOperation(String aName, String aType) throws NoThisShape{ s = factoryMethod(aName, aType); System.out.println("The current shape is: " + s.name); s.draw(); s.erase(); } }
|
测试类:
class Main { public static void main(String[] args) throws NoThisShape{ ShapeFactory.anOperation("Shape one","circle"); ShapeFactory.anOperation("Shape two","square"); ShapeFactory.anOperation("Shape three", "delta"); } }
|
大家知道生成一个数据库的Connection object 是一个非常影响程序速度的操作,所以"连接池'(connection pooling)是一个很常使用的技巧: 程序维持一定数量的Connection object, 以便不断的重用.这样一来就大大减少了产生和销毁Connection object所需的时间.这就要求我们能够控制最多可产生个Connection object. 下面我们看看如和用Factory 模式来解决这个问题:
import java.sql.*; import java.util.*; pulbic class ConnectionPool { private static final int NUM_OF_CONNECTION = 50; private static int counter = 0; private Vector connectionPool = new Vector(); private ConnectionPool(){ } public static Connection getConnection() throws Exception{ Connection connection = null; if (connectionPool.size() < NUM_OF_CONNECTION) { connection = Class.forName("my.sql.Driver"). getConnection("dbc:oracle:thin:@192.168.100.36:1521:ora9i"); connectionPool.add(connection); } else { if(conuter < NUM_OF_CONNECTION) counter++; else
counter = 0; connection = (Connection)connectionPool.elementAT(counter% NUM_OF_CONNECTION ); } return connection; } }
|
阅读(1073) | 评论(0) | 转发(0) |