工厂模式:使用者不用创建使用对象,直接从工厂取出对象进行使用。
示例:子宫(工厂)创造各种动物
工厂模式的优势:在添加动物的时候不需要修改客户端(TestFactoryPattern),只需要直接添加动物就可以,工厂会自动(这时需要一个标示告诉工厂你需要那种动物,也就是type)返回需要的动物。
工厂模式类图:
直接代码:
定义一个抽象类Animal,定义动物的共同属性 name,speed,共同行为:say(),run();,子类可进行覆写方法实现自己特有的行为。
package com.zpj.designMode; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:11:07 * @version :1.1 * */ public abstract class Animal { public String name; public int speed; public abstract void run(); public abstract void say(); public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSpeed() { return speed; } public void setSpeed(int speed) { this.speed = speed; } }
下面添加三个动物:Person Tiger ,Panda
package com.zpj.designMode; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:13:48 * @version :1.1 * */ public class Person extends Animal { public Person() { } public Person(String name, int speed) { this.name = name; this.speed = speed; } @Override public void run() { System.out.println(name + "--两条腿跑---speed:" + speed + "KM/h"); } @Override public void say() { System.out.println(name + "--嘴说--- hello , i am " + name); } }
package com.zpj.designMode; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:18:45 * @version :1.1 * */ public class Tiger extends Animal { public Tiger() { super(); // TODO Auto-generated constructor stub } public Tiger(String name, int speed) { super(); this.name = name; this.speed = speed; } public void run() { System.out.println(name + "--四条腿窜---speed:" + speed); } public void say() { System.out.println(name + "--吼--- hello , i am " + name); } }
package com.zpj.designMode; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:17:45 * @version :1.1 * */ public class Panda extends Animal{ public Panda() { super(); // TODO Auto-generated constructor stub } public Panda(String name,int speed) { this.name = name; this.speed = speed; } public void run() { System.out.println(name + "--四条腿爬---speed:" + speed); } public void say() { System.out.println(name + "--不知道--- hello , i am " + name); } }
创建个子宫(工厂)生产动物
package com.zpj.designMode; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Field; import java.util.Properties; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:21:38 * @version :1.1 * */ public class Uterus { public static Animal createAnimal(int type) {//type 类型告诉工厂客户端需要什么动物 switch (type) { case 1: return new Person("所谓的高级动物", 30); case 2: return new Tiger("老虎", 100); case 3: return new Panda("黑白猫", 10); } return null; } public static Animal createAnimal() throws Exception { //从配置文件中读出客户端需要什么动物 Properties prop = new Properties(); InputStream in = Object.class.getResourceAsStream("/com/zpj/designMode/animal.properties"); try { prop.load(in); String type = prop.getProperty("type").trim(); String name = prop.getProperty("name").trim(); String speed = prop.getProperty("speed").trim(); //使用反射机制生成客户端需要的动物 Class classs = Class.forName(type); Animal animal = (Animal) classs.newInstance(); animal.setName(name); animal.setSpeed(Integer.parseInt(speed)); return animal; } catch (IOException e) { e.printStackTrace(); } return null; } }
测试类:
package com.zpj.designMode; import org.junit.Test; /** * @author PerKins Zhu * @date:2016年8月27日 下午5:39:35 * @version :1.1 * */ public class TestFactoryPattern { @Test public void test01() throws Exception { Animal animal; for (int i = 1; i < 4; i++) { System.out.println("-----------------test:" + i + " -------------------"); animal = Uterus.createAnimal(i); animal.say(); animal.run(); } } //使用配置文件告诉工厂需要什么动物 @Test public void test02() throws Exception { Animal animal; animal = Uterus.createAnimal(); animal.say(); animal.run(); } }
说明一下:
test01()是普通的工厂模式,这里有一个缺陷,就是在增加动物的时候需要更改工厂,在 public static Animal createAnimal(int type)方法中需要添加一种新类型。
test02()是优化后的测试方法,此时调用public static Animal createAnimal() throws Exception (),从配置文件中读取客户端需要的对象,此时如果需要添加动物,只需要修改配置问价就可以了,不需要再对
createAnimal()方法进行修改。
配置文件内容:
type=com.zpj.designMode.Person
name=所谓的高级动物
speed=30
注意:
注意读取配置文件的路径问题
反射机制使用的时候类中必须有空的构造方法。