OOP h18
构造一个「类厂」:MyClassFactory
该类能够用一个 .ini 文件初始化,.ini 文件的格式参考 my_config.ini,测试的时候这个文件名字可能改变,文件中包括中文,且文件一定为 UTF-8 编码
.ini 文件中描述了这个类厂能够动态创建的类和类的初始属性
动态构造各种类,并且用.ini中的属性初始化,测试的时候 类名可能变化,例如 Orange.class ….
测试的时候,可能给其他对象,测试时候给的对象一定满足如下条件:
- 有空的构造函数
- 其中只包括了 Integer,String 两种属性,并且有 setXxx getXxx 方法
将要动态创建的“类”抽象成 Param 类。
0x00 Param
该类应该具有成员变量,存储“类”和属性的对应关系(Map),而属性和属性值也具有对应关系(Map)。
Param 包含成员变量 allParamsMap,类型为 Map<String, Map<String, Object>>
。
构造方法可以直接调用 readLines 读取文件转换格式。
新建 getParamMap 方法,返回对应“类”名的属性映射 Map<String, Object>
。
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| package com.huawei.classroom.student.h18;
import java.io.*; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map;
public class Param {
private final Map<String, Map<String, Object>> allParamsMap = new HashMap<>();
public Param(String filename) throws IOException { readLines(filename); }
public Map<String, Object> getParamMap(String className) { return allParamsMap.get(className); }
private void readLines(String filename) throws IOException { InputStream in = new FileInputStream(filename); InputStreamReader inReader = new InputStreamReader(in, StandardCharsets.UTF_8); LineNumberReader lineReader = new LineNumberReader(inReader); String line = lineReader.readLine();
while (line != null) { if (line.startsWith("#") || line.trim().length() == 0) { } else { String[] strs = line.split("="); String left = strs[0]; String right = strs[1]; int dotPos = left.lastIndexOf("."); String className = left.substring(0, dotPos); String paramName = left.substring(dotPos + 1); Map<String, Object> paramMap = null; if (allParamsMap.containsKey(className)) { paramMap = allParamsMap.get(className); } else { paramMap = new HashMap<>(); } if (right.startsWith("\"")) { paramMap.put(paramName, right.substring(1, right.length() - 1)); } else { paramMap.put(paramName, Integer.parseInt(right)); } allParamsMap.put(className, paramMap); } line = lineReader.readLine(); } } }
|
0x01 MyClassFactory
动态调用赋值,需要给“类”新建 setter 方法(getter 是 Test 用的)。
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package com.huawei.classroom.student.h18;
import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map;
public class MyClassFactory { private final Param params;
public MyClassFactory(String filename) throws IOException { params = new Param(filename); }
public <T> T createInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { String className = clazz.getName(); T t = clazz.newInstance(); Map<String, Object> paramMap = params.getParamMap(className); for (String param : paramMap.keySet()) { Object value = paramMap.get(param); String methodName = "set" + param.substring(0, 1).toUpperCase() + param.substring(1); dynamicInvokeMethod(t, methodName, value); } return t; }
public void dynamicInvokeMethod(Object obj, String methodName, Object... values) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { int i; Class<?>[] classes = new Class[values.length]; for (i = 0; i < values.length; i++) { classes[i] = values[i].getClass(); } Method method = obj.getClass().getMethod(methodName, classes); method.invoke(obj, values); } }
|