可能你还没有见过上面那么多的词,但是你一定用过,下面慢慢解释。
功能是模拟鼠标点击按钮—》触发事件,
客户以后可能会增加需求或删除需求。
界面大概是这样的:
如果一个个按钮写事件的话,会产生很多一样的代码。。而且以后要是客户要加几个按钮,又是一堆差不多的代码复制粘贴,客户又改需求,你又要改改改…很坑。有没有好一点的办法呢?
先看一下uml图
再来看一看代码:
import java.awt.Button;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
interface BaseClass{
//方便实现多态,通过接口实现控制反转,解耦
}
class FJY implements BaseClass{
private String name="fuJingYao";
private String age;
public void show(String age) {
this.age=age;
System.out.println("show name and age:"+name+","+age);
}
}
class LHH implements BaseClass{
private String name="linHuaHua";
private String age;
public void show(String age) {
this.age=age;
System.out.println("show name and age:"+name+","+age);
}
}
class RefLex{
public void buttonClick(HashMap hash,String butName,String age) {
try {
Class<?> cla=Class.forName((String) hash.get(butName));//创建一个类
BaseClass impClass=(BaseClass) cla.newInstance();//获得类的实例
Method method=cla.getMethod("show", String.class);//获得一个show方法,里面传入的是String类型的一个参数
method.invoke(impClass,age);//impClass调用这个方法并传入年龄
} catch (Exception e) {
e.printStackTrace();
}
}
public class Test {
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
HashMap<String,String> hash=new HashMap<String,String>();//按钮名和执行的类相对应、数据驱动操作
hash.put("button1","FJY");
hash.put("button2","LHH");
String buttonName1="button1";//模拟按钮1被点击
String age1="21";//模拟传入的数据
String buttonName2="button2";//模拟按钮2被点击
String age2="31";//模拟传入的数据
RefLex rl=new RefLex();
rl.buttonClick(hash, buttonName1, age1);//模拟鼠标点击按钮
rl.buttonClick(hash, buttonName2, age2);//模拟鼠标点击按钮
}
}
效果:
在上面的代码中,可以看出,如果客户要删除LHH这个按钮,你只需要删除几行代码:
hash.put("button2","LHH");
rl.buttonClick(hash, buttonName2, age2);
客户改需求要删多少都无所谓,轻松。
要是客户需要增加需求呢?
比如说需要加一个按钮可以保存别人的年龄,一样的原理:
1、在hashMap中增加一对键值
2、设置单机事件
3、新建一个类继承BaseClass类,并实现功能
你会发现,RefLex类中的代码根本不需要变动。
下面讲一下题目中的一些专业词:
依赖注入:和控制反转有关联,依赖注入可以实现控制反转。依赖注入包括属性注入,构造方法注入和成员方法注入。打个比方:
class FJY
Private String age;
FJY(String age){
this.age=age;
}
}
这是依赖构造函数注入,还有属性注入和成员方法注入。
比如你一般写的get方法就是其中一种。
控制反转:从主动到被动的过程,在例子中,FJY有一个age属性,常理来说这个属性应该是FJY能设置的(好比生活中我想要喝什么饮料我自己决定,我自己去买就好了。但是控制反转了我就成一个懵逼的人,我不会主动去买饮料,别人给我什么饮料我就喝什么),但是我使用了一个show方法,让这个age从外部可以传进来,FJY只能被动接受这个值了。
反射:刚接触到反射,百度一下原来可以通过类名创建一个类的实例。感觉没什么用,我写了如下代码:
String obj=“FJY";
obj o=new obj();
这样子是不是可以了?我想创建什么类改一下变量名就可以了。哈哈哈。。。
不过很过分的是这是错误的。。不能这样写,那我怎么通过变量名创建类实例呢?就有了反射的用途了!
Class<?> cla=Class.forName((String) hash.get(butName));//创建一个类
BaseClass impClass=(BaseClass) cla.newInstance();//获得类的实例
Method method=cla.getMethod("show", String.class);//获得一个show方法,里面传入的是String类型的一个参数
method.invoke(impClass,age);//impClass调用这个方法并传入年龄
面向接口:在案例中的两个类实现了一个空接口,在RefLex中利用多态new了一个接口的实例对象:
BaseClass impClass=(BaseClass) cla.newInstance();
为什么这样做呢?
因为我不知道用户需要的是哪个类的实例,那我左边就写一个接口,右边是一个接口的实例。这行代码相当于:
BaseClass impClass=new FJY();或者 BaseClass impClass=new LHH();
但是具体new的是哪一个,我不知道,但是左边一定可以写它的接口。这里用到了多态。左抽象右具体嘛。
这样这个软件就高内聚低耦合了。
数据驱动:电脑光盘知道吧,光驱在主机上,你按一下按钮光驱就“咔”的弹出来了,把光盘放进去“啪”关上光驱,你的电脑里就有光盘里的数据了。数据驱动就是把数据当成光盘放进程序里。在这个案例中我的光驱是HashMap。而且这样做方便以后调试。你模拟多少数据都可以通过这个光驱放进去。
以上纯属个人理解,有什么错误虚心求教。