设计模式-工厂方法模式

xiaoxiao2021-02-28  35

例子:女娲造人 类图: 这个过程我们就用程序来实现,首先定义一个人类的总称:

/** * Created by xpeng on 2018/5/1. * 定义一个人类的统称 */ public interface Human { //首先定义什么是人类 //人是会笑的 public void laugh(); //人类还会哭 public void cry(); //人类会说话 public void talk(); }

然后定义具体的人类:

/** * Created by xpeng on 2018/5/1. * 黄色人类 */ public class YellowHuman implements Human { @Override public void cry() { Log.e("xyz","黄色人类会哭"); } @Override public void laugh() { Log.e("xyz","黄色人类会笑"); } @Override public void talk() { Log.e("xyz","黄色人类会说话"); } } /** * Created by xpeng on 2018/5/1. * 白色人类 */ public class WhiteHuman implements Human { @Override public void cry() { Log.e("xyz","白色人类会哭"); } @Override public void laugh() { Log.e("xyz","白色人类会笑"); } @Override public void talk() { Log.e("xyz","白色人类会说话"); } } /** * Created by xpeng on 2018/5/1. * 黑色人类 */ public class BlackHuman implements Human { @Override public void cry() { Log.e("xyz","黑色人类会哭"); } @Override public void laugh() { Log.e("xyz","黑色人类会笑"); } @Override public void talk() { Log.e("xyz","黑色人类会说话"); } }

定义八卦炉(工厂)

/** * Created by xpeng on 2018/5/1. * 女娲八卦炉造人 */ public class HumanFactory { //定一个烤箱,泥巴塞进去,人就出来,这个老厉害了 public static Human createHuman(Class c) { Human human = null; try { human = (Human) Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { Log.e("xyz", " 必须指定人类的颜色 "); } catch (IllegalAccessException e) {//定义的人类有问题 Log.e("xyz", " 人类定义错误! "); } catch (ClassNotFoundException e) { Log.e("xyz", " 混蛋,你指定的人类找不着 "); } return human; } }

女娲大神造人了

Log.e("xyz"," 造出的第一批人是这样的:白人 "); Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class); whiteHuman.cry(); whiteHuman.laugh(); whiteHuman.talk(); Log.e("xyz"," 造出的第二批人是这样的:黑人 "); Human blackHuman = HumanFactory.createHuman(BlackHuman.class); blackHuman.cry(); blackHuman.laugh(); blackHuman.talk(); Log.e("xyz"," 造出的第二批人是这样的:黄色人类 "); Human yellowHuman = HumanFactory.createHuman(YellowHuman.class); yellowHuman.cry(); yellowHuman.laugh(); yellowHuman.talk();

人有了,但是这样创建太累了,神仙也会累的,那怎么办?我塞进去一团泥巴,随机出来一群人,管他什么颜色呢,只要是人就行。 类图:

/** * Created by xpeng on 2018/5/1. * 女娲八卦炉造人 */ public class HumanFactory { //定一个烤箱,泥巴塞进去,人就出来,这个老厉害了 public static Human createHuman(Class c) { Human human = null; try { human = (Human) Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { Log.e("xyz", " 必须指定人类的颜色 "); } catch (IllegalAccessException e) {//定义的人类有问题 Log.e("xyz", " 人类定义错误! "); } catch (ClassNotFoundException e) { Log.e("xyz", " 混蛋,你指定的人类找不着 "); } return human; } //女娲生气了,把一团泥巴塞到八卦炉,爱产生啥人类就啥人类 public static Human createHuman() { Human human = null;//定义一个类型的人类 try { //定义了多少人类 List<Class> concreateHumanList = ClassUtils.getAllClassByInterface(Human.class); //八卦炉自己开始想烧出什么人就什么人 Random random = new Random(); int rand = random.nextInt(concreateHumanList.size()); human = createHuman(concreateHumanList.get(rand)); }catch (Exception e){ Log.e("xyz","这里需要好好思考研究"); } return human; } }

女娲生气了,把一团泥巴塞进去,爱出来什么颜色的人类随意

//女娲生气了,把一团泥巴塞到八卦炉,爱产生啥人类就啥人类 public static Human createHuman() { Human human = null;//定义一个类型的人类 try { //定义了多少人类 List<Class> concreateHumanList = ClassUtils.getAllClassByInterface(Human.class); //八卦炉自己开始想烧出什么人就什么人 Random random = new Random(); int rand = random.nextInt(concreateHumanList.size()); human = createHuman(concreateHumanList.get(rand)); }catch (Exception e){ Log.e("xyz","这里需要好好思考研究"); } return human; }

这里还需要一个类,ClassUtils

/** * Created by xpeng on 2018/5/2. */ public class ClassUtils { //给一个接口,返回这个接口的所有实现类 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 (!c.equals(allClass.get(i))) {//本身不加进去 returnClassList.add(allClass.get(i)); } } } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return returnClassList; } //从一个包中查找所有的类,在jar包中不能查找 private static List<Class> getClasses(String packageName) throws ClassNotFoundException, IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); String path = packageName.replace('.', '/'); 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; } }

这个ClassUtils可是个宝,用处可大了去了,可以由一个接口查找所有实现的类,也可以由父类查找到所有的子类,这个要自己修改一下,需要思考一下 完整类图:

总结一下,特别是增加了createHuman()后,是不是这个工厂vhangde扩展性更好了?只要你继续集成Human接口就成了,然后啥也不用修改就可以生产了,具体产多少,八卦炉说了算,简单工厂模式就是这么简单。

工厂方法模式还有一个非常重要的应用,就是延迟始化,直接从内存中拿就行了,怎么实现呢,很简单:

/** * Created by xpeng on 2018/5/1. * 女娲八卦炉造人 */ public class HumanFactory { //定义一个MAP,初始化过的Human对象都放在这里 private static HashMap<String,Human> humans = new HashMap<String,Human>(); //定一个烤箱,泥巴塞进去,人就出来,这个老厉害了 public static Human createHuman(Class c) { Human human = null; try { //如果MAP中有,则直接从中取出,不用初始化 if (humans.containsKey(c.getSimpleName())){ //产生一个人类 human = humans.get(c.getSimpleName()); }else { human = (Human) Class.forName(c.getName()).newInstance(); //放到MAP中 humans.put(c.getSimpleName(),human); } } catch (InstantiationException e) { Log.e("xyz", " 必须指定人类的颜色 "); } catch (IllegalAccessException e) {//定义的人类有问题 Log.e("xyz", " 人类定义错误! "); } catch (ClassNotFoundException e) { Log.e("xyz", " 混蛋,你指定的人类找不着 "); } return human; } //女娲生气了,把一团泥巴塞到八卦炉,爱产生啥人类就啥人类 public static Human createHuman() { Human human = null;//定义一个类型的人类 try { //定义了多少人类 List<Class> concreateHumanList = ClassUtils.getAllClassByInterface(Human.class); //八卦炉自己开始想烧出什么人就什么人 Random random = new Random(); int rand = random.nextInt(concreateHumanList.size()); human = createHuman(concreateHumanList.get(rand)); }catch (Exception e){ Log.e("xyz","这里需要好好思考研究"); } return human; } }

就是定义一个MAP,这个类初始化很消耗资源的情况下比较实用,比如你要连接硬件,或者初始化一个类需要准备比较多的条件(参数),通过这种方式可以减少项目的复杂度。 最后引入一个问题:人是有性别的啊,有男有女,你这怎么没区别,这个需要下一个讲的模式:抽象工厂模式

转载请注明原文地址: https://www.6miu.com/read-2627979.html

最新回复(0)