《您的设计模式》(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(); } } }
工厂方法模式还有一个非常重要的应用,就是延迟初始化,什么是延迟初始化呢?一个对象初始化完毕后就不释放,等到再次用到就不用再次初始化了,直接从内存中拿到就可以了。
相关文章推荐
- 《您的设计模式》(CBF4LIFE)之“访问者模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“责任链模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“多例模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“状态模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“抽象工厂模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“组合模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“桥梁模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“策略模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“单例模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“代理模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“迭代器模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“模板方法模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“适配器模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“建造者模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“装饰模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“门面模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“命令模式”【整理】
- 《您的设计模式》(CBF4LIFE)之“观察者模式”【整理】
- 收藏别人整理的 设计模式(设计模式(2): 工厂方法模式 )
- .NET设计模式之工厂方法模式