一、引子 


            话说十年前,有一个用户,他家有三辆汽车——Benz奔驰、Bmw宝马、Audi奥迪,还雇了司机为他开车。不过,用户坐车时总是怪怪的:上Benz车后跟司机说“开奔驰车!”,坐上Bmw后他说“开宝马车!”,坐上Audi说“开奥迪车!”。你一定说:这人有病!直接说开车不就行了?! 


             而当把这个用户的行为放到我们程序设计中来时,会发现这是一个普遍存在的现象。幸运的是,这种有病的现象在OO(面向对象)语言中可以避免了。下面就以Java语言为基础来引入我们本文的主题:工厂模式。 

二、分类


1)简单工厂模式(Simple Factory) 

2)工厂方法模式(Factory Method) 

3)抽象工厂模式(Abstract Factory) 
             这三种模式从上到下逐步抽象,并且更具一般性。


三、代码


1.说明:


装扮操作,客户通过点击不同的头发,便会生成不同的对象,那么当我们想新增加一个头发类型时,如果不用工厂模式,那么就去多添加else if 去新生成一个新的对象给客户端,这个每添加一个类就要去改动一下代码的方式极不合适,这时我们就用到了工厂,通过头发生成工厂,我们只会需要改一个配置文件,同时告诉客户端我们有这个 新的对象可以使用,那么客户就可以直接使用了。


头发接口

Hair.java

package com.lei.model;

public interface Hair {
	
	public void drawHair();
}

BlueHair.java

package com.lei.model.impl.hair;

import com.lei.model.Hair;

public class BlueHair implements Hair {

	@Override
	public void drawHair() {
		System.out.println("----------蓝色头发---------------");
	}

}

BlackHair.java

package com.lei.model.impl.hair;

import com.lei.model.Hair;

public class BlackHair implements Hair {
	
	@Override
	public void drawHair() {
		System.out.println("---------黑色头发------------");
	}

}

RedHair.java


package com.lei.model.impl.hair;

import com.lei.model.Hair;

public class RedHair implements Hair {
	
	@Override
	public void drawHair() {
		System.out.println("-------------红色头发-----------");
	}

}

读取配置文件工具类


PropertiesReadUtil

package com.lei.utils;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


public class PropertiesReadUtil {
	
	public  Map<String, String> getProperties(){
		
		Map<String,String> map = new HashMap<>();
		
		Properties properties = new Properties();
		
		try {
			InputStream in = getClass().getResourceAsStream("/com/lei/pro/hair.properties");
			properties.load(in);
			
			Enumeration<Object> ens = properties.keys();
			while (ens.hasMoreElements()) {
				String key = (String) ens.nextElement();
				String value = properties.getProperty(key);
				map.put(key, value);
			}
			return map;
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}


}

生成头发工厂


HairFactory.java


package com.lei.utils;

import java.util.Map;
import java.util.Properties;

import com.lei.model.Hair;

/**
 * 生产头发的工厂
 * @author pibigstar
 *
 */
public class HairFactory {
	
	
	
	
	
	public Hair getHairByKey(String key){
		
		PropertiesReadUtil pr = new PropertiesReadUtil();
		Map<String, String> map = pr.getProperties();
		try {
			//通过反射机制,生成对像,通过key得到类名,通过类名生成对应的对象
			Hair hair = (Hair) Class.forName(map.get(key)).newInstance();
			return hair;
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		return null;
		
	}
	
	public Hair getHairByClassName(String className){
		
		try {
			/*通过反射机制,生成对像,通过类名去生成一个对象
			*这样你就算增加了新的类,只要告诉客户端有这个类,不需要改动任何代码就可以动态的生成这个新类的对象
			*
			*/
			Hair hair = (Hair) Class.forName(className).newInstance();
			return hair;
		} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}


}

配置文件


hair.properties


red=com.lei.model.impl.hair.RedHair
black=com.lei.model.impl.hair.BlackHair
blue=com.lei.model.impl.hair.BlueHair

测试类


FactoryTest.java


package com.lei.test;

import com.lei.model.Hair;
import com.lei.utils.HairFactory;

public class FactoryTest {
	
	public static void main(String[] args) {
		
//		HairFactory factory = new HairFactory();
//		Hair hair = factory.getHairByClassName("com.lei.model.impl.hair.BlueHair");
//		
//		hair.drawHair();
		
		HairFactory factory = new HairFactory();
		Hair hair = factory.getHairByKey("red");
		hair.drawHair();
		
	}

}