设计模式总结之工厂模式 (Factory)

工厂方法模式,定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类的实例化推迟到子类。

简单工厂模式的区别是工厂方法是具体的,不需要推迟到子类。

抽象工厂方法模式,提供一个接口,用于创建相关依赖对象的家族,而不需要明确指定具体类。

下面以剪头发为例来实现工厂方法:

发型工厂

package com.sunny.project;

import java.util.Map;

/**
 * 发型工厂
 * @author Administrator
 *
 */
public class HairFactory {

	/**
	 * 根据类型来创建对象
	 * @param key
	 * @return
	 */
	public HairInterface getHair(String key){
		if("left".equals(key)){
			return new LeftHair();			
		}else if("right".equals(key)){
			return new RightHair();
		}
		return null;
	}
	/**
	 * 根据类的名称来生产对象
	 * @param className
	 * @return
	 */
	public HairInterface getHairByClass(String className){
		
		try {
			HairInterface hair = (HairInterface) Class.forName(className).newInstance();
			return hair;
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 根据类的名称来生产对象
	 * @param className
	 * @return
	 */
	public HairInterface getHairByClassKey(String key){
		
		try {
			Map<String, String> map = new PropertiesReader().getProperties();
			
			HairInterface hair = (HairInterface) Class.forName(map.get(key)).newInstance();
			return hair;
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}

 发型接口类

package com.sunny.project;
/**
 * 发型接口
 * @author Administrator
 *
 */
public interface HairInterface {

	/**
	 * 画图
	 */
	public void draw();
}

 中分发型实现类

package com.sunny.project;
/**
 * 中分发型
 * @author Administrator
 *
 */
public class InHair implements HairInterface {

	@Override
	public void draw() {
		// TODO Auto-generated method stub
		System.out.println("-----------------中分发型-------------------");
	
	}

}

 配置读取工具类(配置内容为in=com.sunny.project.InHair)

package com.sunny.project;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * properties文件的读取工具
 * @author Administrator
 *
 */
public class PropertiesReader {

	
	public Map<String, String> getProperties() {

		Properties props = new Properties();
		Map<String, String> map = new HashMap<String, String>();
		try {

			InputStream in = getClass().getResourceAsStream("type.properties");
			props.load(in);
			Enumeration en = props.propertyNames();
			while (en.hasMoreElements()) {
				String key = (String) en.nextElement();
				String property = props.getProperty(key);
				map.put(key, property);
//				System.out.println(key + "  " + property);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
}

 测试类

package com.sunny.project;

public class SunnyTest {

	public static void main(String[] args){
		
		HairFactory factory = new HairFactory();
		
		HairInterface hair = factory.getHairByClassKey("in");
		hair.draw();

	}
} 

工厂方法模式

优点:

 1. 良好的封装性,代码结构清晰。一个对象创建是有条件约束的,如一个调用者需要 一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,减少模块间的耦合。

 2. 工厂方法模式的扩展性非常优秀。在增加产品类的情况下,只要适当地修改具体的 工厂类或扩展一个工厂类,就可以完成“拥抱变化”。

 3. 屏蔽产品类。这一特点非常重要,产品类的实现如何变化,调用者都不需要关心, 它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化,因为产品类的实例化工作是由工厂类负责,一个产品对象具体由哪一个产品生成是由工厂类决定的。在数据库开发中,大家应该能够深刻体会到工厂方法模式的好处:如果使用JDBC连接数据库,数据库从MySql切换到Oracle,需要改动地方就是切换一下驱动名称(前提条件是SQL语句是标准语句),其他的都不需要修改,这是工厂方法模式灵活性的一个直接案例。

 4. 工厂方法模式是典型的解耦框架。高层模块值需要知道产品的抽象类,其他的实现 类都不用关心,符合迪米特原则,我不需要的就不要去交流;也符合依赖倒转原则,只依赖产品类的抽象;当然也符合里氏替换原则,使用产品子类替换产品父类,没问题!  

用途: 第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂, 生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。  第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。

抽象工厂模式

优点:

 1. 抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建

 2. 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一 个产品族中的对象

 3. 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”

缺点:  增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。

用途:

 1、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。

 2、系统中有多于一个的产品族,而每次只使用其中某一产品族。

 3、属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。

 4、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

猜你喜欢

转载自408599764.iteye.com/blog/2293307
今日推荐