package org.rui.pattern2; import java.util.*; import junit.framework.*; /** * (实现 factory 模式)常用的方法是把 factory 声明为基类的静态方法(static method) * * @author Administrator * */ abstract class Shape { public abstract void draw(); public abstract void erase(); public static Shape factory(String type) { if (type.equals("Circle")) return new Circle(); if (type.equals("Square")) return new Square(); throw new RuntimeException("Bad shape creation: " + type); } } class Circle extends Shape { Circle() { } // Package-access constructor public void draw() { System.out.println("Circle.draw"); } public void erase() { System.out.println("Circle.erase"); } } class Square extends Shape { Square() { } // Package-access constructor public void draw() { System.out.println("Square.draw"); } public void erase() { System.out.println("Square.erase"); } } public class ShapeFactory1 extends TestCase { String shlist[] = { "Circle", "Square", "Square", "Circle", "Circle", "Square" }; List shapes = new ArrayList(); public void test() { Iterator it = Arrays.asList(shlist).iterator(); while (it.hasNext()) shapes.add(Shape.factory((String) it.next())); it = shapes.iterator(); while (it.hasNext()) { Shape s = (Shape) it.next(); s.draw(); s.erase(); } } public static void main(String args[]) { junit.textui.TestRunner.run(ShapeFactory1.class); } } // /:~ /** * factory() 方法需要传入一个参数来决定要创建的 Shape 的具体类型; 在上面的 * 例子里(参数)碰巧是一个字符串(String),它也可以是其它任意类型。当加入新 的 Shape * 类型的时候(我们假定被创建对象的初始化代码是来自系统以外的,而不是 像上面那个例子使用一个硬编码(hard-coded)的数组),系统唯一需要改动的代码 * 就是 factory( )方法。为了促使创建对象的代码只包含在 factory( )方法里,特定类 型的 Shape 类的构造函数都被声明为 * package 权限,这样一来只有 factory( )方法可 以调用这些构造函数,而位于包(package)以外的那部分代码则没有足够的权限(调 * 用这些构造函数)。 */
package org.rui.pattern2; import java.util.*; import junit.framework.*; /** * 上例中,静态的 factory( )方法使得所有创建对象的操作都集中在一个地方完 * 成,这也就是唯一需要你修改代码的地方。这当然是一个还算不错的的解决办法,它 封装了创建对象的过程。然而,《设计模式》强调使用 Factory Method * 是为了使不同 类型的工厂可以由基本类型的工厂派生(subclass)出来(上面例子是一个特例)。 * 但是,那本书没有给出具体例子,只是重复了用于说明抽象工厂(Abstract Factory)的那个例子(你会在本书下一节看到一个 Abstract * Factory 的例子)。下 面的例子,我们修改了 ShapeFactory1.java 使得工厂方法成为一个单独的类的虚函 数。请注意,特定类型的 * Shape 类是根据需要动态加载的。 * * @author Administrator * */ interface Shape2 { void draw(); void erase(); } abstract class ShapeFactory { protected abstract Shape2 create(); private static Map factories = new HashMap(); public static void addFactory(String id, ShapeFactory f) { factories.put(id, f); } public static final Shape2 createShape(String id) { if (!factories.containsKey(id)) { try { // 动态加载 Class.forName("org.rui.pattern2." + id); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException("Bad shape creation: " + id); } // 看看这是: if (!factories.containsKey(id)) throw new RuntimeException("Bad shape creation: " + id); } //从加过到集合里获取对象 内部类继承ShapeFactory create返回外部类对象Shape2 return ((ShapeFactory) factories.get(id)).create(); } } // ------------------------------------------------------------------- class Circle2 implements Shape2 { private Circle2() { } public void draw() { System.out.println("Circle.draw"); } public void erase() { System.out.println("Circle.erase"); } //内部类 private static class Factory extends ShapeFactory { //返回外部类对象 protected Shape2 create() { return new Circle2(); } } // 初始化时把对象加入工厂Map集合中 static { ShapeFactory.addFactory("Circle", new Factory()); } } // --------------------------------------------------------------------------- class Square2 implements Shape2 { private Square2() { } public void draw() { System.out.println("Square.draw"); } public void erase() { System.out.println("Square.erase"); } private static class Factory extends ShapeFactory { protected Shape2 create() { return new Square2(); } } static { ShapeFactory.addFactory("Square2", new Factory()); } } // -------------------------------------------------- public class ShapeFactory2 extends TestCase { String shlist[] = { "Circle2", "Square2", "Square2", "Circle2", "Circle2", "Square2" }; List shapes = new ArrayList(); public void test() { // T这只是确保它将完成 // 没有抛出异常 Iterator it = Arrays.asList(shlist).iterator(); while (it.hasNext()) shapes.add(ShapeFactory.createShape((String) it.next())); it = shapes.iterator(); while (it.hasNext()) { Shape2 s = (Shape2) it.next(); s.draw(); s.erase(); } } public static void main(String args[]) { junit.textui.TestRunner.run(ShapeFactory2.class); } } // /:~ /** * 现在工厂方法(factory method)出现在它自己的类 ShapeFactory 里,名字改成了 create( * )方法。它是一个受保护的(protected)方法,也就是说它不能被直接调 用,但可以被重载。Shape 类的子类必须创建与之对应的 * ShapeFactory 的子类,并且 通过重载 create( )函数来创建它自己的实例。实际上一系列 Shape 对象的创建是通过 调用 * ShapeFactory.createShape( ) 来完成的。 CreateShape( )是个静态方法, 它 根据传入的标示,通过查找 * ShapeFactory 的 Map 成员变量找到与之相应的工厂对 象 (factory obejct)。 然后,找到的 factory 对象即被用来创建 * shape 对象,但 你可以想象一下更为棘手的问题:(与某种 Shape 类型相对应的)工厂对象被调用者 * 用来以更为复杂的方式创建对象。但是,大多数情况下你似乎并不需要用到复杂的多 态工厂方法(polymorphic factory * method),在基类里加一个静态方法(像 ShapeFactory1.java 那样)就足以解决问题了。 * * 注意到,ShapeFactory 的初始化必须通过加载 Map 数据成员才能完成(Map 的元 素是 factory 对象),而这些初始化代码又位于 * Shape 实现类的静态初始化语句里。 这样一来,每加入一个新的类型你就必须得继承原来的类型(指 Shape?),创建一个 * factory,然后添加静态初始化语句用以加载 Map 对象。这些额外的复杂性又一次暗示 我们:如果不需要创建单独的 factory * 对象,那最好还是使用静态工厂方法。 */
---------------------------------------------------------------
package org.rui.pattern2; /** * 抽象工厂(Abstract factories) */ interface Obstacle { void action(); } interface Player { void interactWith(Obstacle o); } class Kitty implements Player { public void interactWith(Obstacle ob) { System.out.println("Kitty has encountered a "); ob.action(); } } class KungFuGuy implements Player { public void interactWith(Obstacle ob) { System.out.println("KungFuGuy now battles a "); ob.action(); } } class Puzzle implements Obstacle { public void action() { System.out.println("Puzzle"); } } class NastyWeapon implements Obstacle { public void action() { System.out.println("NastyWeapon"); } } // The Abstract Factory: interface GameElementFactory { Player makePlayer(); Obstacle makeObstacle(); } // Concrete factories: class KittiesAndPuzzles implements GameElementFactory { //实例子类返回父类似 public Player makePlayer() { return new Kitty(); } //实例子类返回父类似 public Obstacle makeObstacle() { return new Puzzle(); } } class KillAndDismember implements GameElementFactory { public Player makePlayer() { return new KungFuGuy(); } public Obstacle makeObstacle() { return new NastyWeapon(); } } //游戏环境 class GameEnvironment { private GameElementFactory gef; private Player p; private Obstacle ob; /** * 通过工厂获得需要的对象实例 * @param factory */ public GameEnvironment(GameElementFactory factory) { gef = factory; p = factory.makePlayer(); ob = factory.makeObstacle(); //System.out.println("ob:"+ob); } public void play() { p.interactWith(ob); } }
package org.rui.pattern2; import junit.framework.TestCase; /** 抽象工厂(abstract factory)模式看起来很像前面我们看到的那些 factory 对 象,只不过它有多个而不是一个 factory 方法。每一个 factory 方法创建一个不同类 型的对象。基本思想是:在创建工厂对象的地方,由你来决定如何使用该工厂对象创 建的那些对象。《设计模式》里给出的例子实现了在不同用户图形界面(GUIs)之间 的可移植性:你根据自己使用的 GUI 来创建一个与之对应的 factory 对象,在这以 后,当你需要用到菜单,按钮,滚动条这些东西的时候,它会根据你使用的 GUI 自动 创建合适的对象。这样,你就可以把实现不同 GUI 之间切换的代码分离出来,使它集 中在一个地方。 作为另外一个例子,假设你要创建一个通用的游戏环境,而且你还想要支持不同 类型的游戏。下面的例子用抽象工厂给出了它的一种可能的实现。 * @author Administrator * */ public class Games extends TestCase { GameElementFactory kp = new KittiesAndPuzzles(), kd = new KillAndDismember(); GameEnvironment g1 = new GameEnvironment(kp), g2 = new GameEnvironment(kd); // These just ensure no exceptions are thrown: public void test1() { g1.play(); } public void test2() { g2.play(); } public static void main(String args[]) { junit.textui.TestRunner.run(Games.class); } } // /:~ /** 在上面的游戏环境里,Player 对象与 Obstale 对象交互,根据你所选择的游戏类 型,player 和 obstacle 的各自类型也会不同。你通过选择某个特定的 GameElementFactory 来决定游戏的类型,然后 GameElementFactory 会控制初始化和游 戏的进行。在上面的例子里,初始化和游戏的进行都非常简单,但那些活动(初始条 件和状态变化)可以在很大程度上决定游戏的结局。这里,GameEnvironment 不是用来 给其它类继承的 ,尽管那么做很可能也说的通。 上面的代码也包含了双重分派(Double Dispatching)和工厂方法(Factory Method)两种模式,我们会在后面讲解它们。 */
时间: 2024-10-09 22:40:55