java 简单工厂模式、多态工厂、抽像工厂 讲解, 代码示例

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

java 简单工厂模式、多态工厂、抽像工厂 讲解, 代码示例的相关文章

抽象工厂模式(abstarct factory pattern)和工厂模式(factory pattern)的比较

抽象工厂模式和工厂模式从字面上来看就有必然的联系,他们都是创建型模式.总结来说,工厂模式(factory pattern)只是个小工厂,只提供一层接口的实现类的输出,而抽象工厂模式(abstract factory pattern)是工厂模式的进一步升级,可以上升到两层以上的工厂模式继承,是工厂的工厂.一计算机来说,工厂模式可以是不同型号显示器,CPU或者网卡的提供者,而抽象工厂模式是显示器工厂.CPU工厂和网卡工厂的工厂.可以通过抽象工厂来获得CPU工厂,进而获得某个型号的CPU.整个依赖关系

终极版:由简单工厂模式,升级到抽象工厂模式(用到反射)

前面两个已经学习简单三层到简单工厂模式的变化,但是简单工厂模式还是有个缺点,就是简单工厂中集合了所有的实例的创建.也不是很好. 现在想到使用抽象工厂的方式来实现这个: 我们在程序集中加上下面的代码: <appSettings> <!--命名空间--> <add key="DALNameSpace" value="DAL"/> <!--程序集--> <add key="DALAssembly"

工厂模式(Factory)和抽象工厂模式(Abstract Factory)

一.工厂模式(Factory):通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的,工厂方法让类的实例化推迟到子类 (1)涉及角色:抽象产品,具体产品,抽象创建者,具体创建者.                (2)实例:    抽象产品类 1 public abstract class ProductNoodle { 2 public abstract String description(); 3 } 具体产品类 1 public class ConcreteNoodleA e

设计模式之原型模式(Prototype)详解及代码示例

一.原型模式的定义与特点 原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象.它属于创建型设计模式,用于创建重复的对象,同时又能保证性能(用这种方式创建对象非常高效). 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆.当直接创建对象的代价比较大时,则采用这种模式.例如,一个对象需要在一个高代价的数据库操作之后被创建.我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用.

设计模式之策略模式(Strategy)详解及代码示例

一.策略模式的定义 策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户.策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理. 二.策略模式优缺点 策略模式的主要优点如下. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件转移语句. 符合开闭原则,可以在不修改原代码的情况下,灵活增加新算法. 算法使用和实现隔离分离,提高算法的保密性和

java进阶之工厂模式(二)抽象工厂模式

public interface KitchenFactory{ //抽象工厂 public Food getFood(); 抽象方法 public TableWare getTableWare(); } public interface Food{ //抽象食物 public String getFoodName(); } public interface TableWare{ public String getToolName(); //抽象餐具 } public class AKitche

Java三大器之拦截器(Interceptor)的实现原理及代码示例

前言:前面2篇博客,我们分析了Java中过滤器和监听器的实现原理,今天我们来看看拦截器. 1,拦截器的概念    java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式.在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截然后再之前或者之后加入某些操作.目前,我们需要掌握的主要是Spring的拦截器,Struts2的拦截器

设计模式之代理模式(Proxy)详解及代码示例

一.代理模式的定义 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介,代理模式也叫做委托模式. 二.为什么使用代理模式 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口. 开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委

java通过配置文件(Properties类)连接Oracle数据库代码示例

1 import java.io.FileInputStream; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.sql.Connection; 5 import java.sql.DriverManager; 6 import java.sql.ResultSet; 7 import java.sql.SQLException; 8 import java.sql.Statement; 9 i

Java工厂模式(简单工厂、工厂方法、抽象工厂)

工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory Method).3:抽象工厂(Abstract Factory). 简单工厂(Simple Factory)又叫静态工厂,是工厂模式三中状态中结构最为简单的.主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例.我们来看一个具体的例子:假设一家工厂,几生产洗衣机,有生产冰箱