您的位置:首页 > Web前端

《您的设计模式》(CBF4LIFE)之“工厂方法模式”【整理】

2016-10-27 10:33 295 查看
故事背景:女娲造人,女娲架起八卦炉(技术术语:建立工厂)开始创建人,具体过程是这样的:先是捏泥巴,然后放八卦炉里烤,再扔到地上成长,但是意外总是会产生的:

第一次烤泥人,一个白人诞生了;第二次烤泥人,一个黑人;第三次烤泥人,黄种人。

首先定义一个人类总称:

package com.teng.pattern.impl;

/**
* 人类接口
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public interface Human {

/**
* 哭
* @since 1.0
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月22日 下午10:29:39
*/
public void cry();

/**
* 笑
* @since 1.0
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月22日 下午10:29:54
*/
public void laugh();

/**
* 说
* @since 1.0
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月22日 下午10:30:09
*/
public void talk();

}


然后定义具体人种:

package com.teng.pattern.impl;

/**
* 白种人
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class WhiteHuman implements Human {

@Override
public void cry() {
System.out.println("白种人哭。。。");
}

@Override
public void laugh() {
System.out.println("白种人笑。。。");
}

@Override
public void talk() {
System.out.println("白种人说。。。");
}

}

package com.teng.pattern.impl;

/**
* 黄种人
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class YellowHuman implements Human {

@Override
public void cry() {
System.out.println("黄种人哭。。。");
}

@Override
public void laugh() {
System.out.println("黄种人笑。。。");
}

@Override
public void talk() {
System.out.println("黄种人说。。。");
}

}

package com.teng.pattern.impl;

/**
* 黑种人
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class BlackHuman implements Human {

@Override
public void cry() {
System.out.println("黑种人哭。。。");
}

@Override
public void laugh() {
System.out.println("黑种人笑。。。");
}

@Override
public void talk() {
System.out.println("黑种人说。。。");
}

}

定义八卦炉(工厂):

package com.teng.pattern.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Random;

import com.teng.pattern.utils.ClassUtils;

/**
* 工厂类
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class HumanFactory {

//定义一个Map 初始化过的Human对象都放在这里
//在类初始化很消耗资源的情况下,很实用
private static HashMap<String,Human> map = new HashMap<String,Human>();

/**
* 工厂方法——指定人种
* @since 1.0
* @param c c
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月22日 下午10:47:04
*/
public static Human createHuman(Class c){
Human human = null;
try {
//如果map中有,则直接取出,不用初始化了。类似于memcached?
if(map.containsKey(c.getSimpleName())){
human = map.get(c.getSimpleName());
}else{
human = (Human)Class.forName(c.getName()).newInstance();
//放到Map中
map.put(c.getSimpleName(), human);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return human;
}

/**
* 工厂方法——随机产生人种
* @since 1.0
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月26日 上午10:17:12
*/
public static Human createHuman(){
Human human = null;
//首先获得有多少个实现类,多少个人种
List<Class> humanClassList = ClassUtils.getAllClassByInterface(Human.class);

//八卦炉自己开始想烧出什么人就烧出什么人
Random random = new Random();
int rand = random.nextInt(humanClassList.size());
human = createHuman(humanClassList.get(rand));
return human;
}
}

相关的工具类:

package com.teng.pattern.utils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

/**
* 由一个接口,查找到所有的实现类
* <br>创建日期:2016年6月26日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class ClassUtils {

/**
* 给一个接口,返回这个接口的所有实现类
* @since 1.0
* @param c c
* @return
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月26日 上午10:37:29
*/
public static List<Class> getAllClassByInterface(Class c){
List<Class> returnClassList = new ArrayList<Class>();

//如果不是接口,则不做处理
if(c.isInterface()){
String packageName = c.getPackage().getName();
try{
//获取当前包下,以及子包下的所有类
List<Class> allClass = getClasses(packageName);

//判断是否是同一个接口
for(int i = 0; i < allClass.size() ;i++){
//判断是是不是一个接口
if(c.isAssignableFrom(allClass.get(i))){
if(!(allClass.get(i)).equals(c)){//本身不加进去
returnClassList.add(allClass.get(i));
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
return returnClassList;
}

//从一个包中查出所有的类,在jar包中不能查找
private static List<Class> getClasses(String packageName) throws IOException, ClassNotFoundException{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
String path = packageName.replace(".", "/");
//由路径,获取该路径下的所有文件的URL
Enumeration<URL> resources = classLoader.getResources(path);
//获取该路径下的所有文件
List<File> dirs = new ArrayList<File>();
while(resources.hasMoreElements()){
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList<Class> classes = new ArrayList<Class>();
for(File directory : dirs){
classes.addAll(findClasses(directory,packageName));
}
return classes;
}

private static List<Class> findClasses(File directory,String packageName) throws ClassNotFoundException{
List<Class> classes = new ArrayList<Class>();
//如果路径不存在,则返回
if(!directory.exists()){
return classes;
}
File[] files = directory.listFiles();
for(File file : files){
if(file.isDirectory()){//如果文件为文件夹,则递归调用
assert !file.getName().contains(".");
classes.addAll(findClasses(file,packageName+"."+file.getName()));
}else if(file.getName().endsWith(".class")){
classes.add(Class.forName(packageName + '.'+file.getName().substring(0, file.getName().length()-6)));
}
}
return classes;
}
}

女娲开始造人:

package com.teng.pattern;

import com.teng.pattern.impl.BlackHuman;
import com.teng.pattern.impl.Human;
import com.teng.pattern.impl.HumanFactory;
import com.teng.pattern.impl.YellowHuman;

/**
* 造物主
* <br>创建日期:2016年6月22日
* <br><b>Copyright 2016 tengxiang All Rights Reserved</b>
* @author tengxiang
* @since 1.0
* @version 1.0
*/
public class God {

/**
* 主方法
* @since 1.0
* @param args
* <br><b>作者: @author tengxiang</b>
* <br>创建时间:2016年6月22日 下午10:55:37
*/
public static void main(String[] args){

Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);
yellowHuman.cry();
yellowHuman.laugh();
yellowHuman.talk();

Human blackHuman = HumanFactory.createHuman(BlackHuman.class);
blackHuman.cry();
blackHuman.laugh();
blackHuman.talk();

//...
//随机产生人种
for(int i = 0; i <10000 ;i++){
Human human = HumanFactory.createHuman();
System.out.println("随机产生人种。。。。。。");
human.cry();
human.laugh();
human.talk();
}
}
}

工厂方法模式还有一个非常重要的应用,就是延迟初始化,什么是延迟初始化呢?一个对象初始化完毕后就不释放,等到再次用到就不用再次初始化了,直接从内存中拿到就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 java 技术