案例:模拟鼠标点击按钮触发事件(包含依赖注入、控制反转、反射、面向接口、数据驱动)

可能你还没有见过上面那么多的词,但是你一定用过,下面慢慢解释。

功能是模拟鼠标点击按钮—》触发事件,
客户以后可能会增加需求或删除需求。

界面大概是这样的:
在这里插入图片描述

如果一个个按钮写事件的话,会产生很多一样的代码。。而且以后要是客户要加几个按钮,又是一堆差不多的代码复制粘贴,客户又改需求,你又要改改改…很坑。有没有好一点的办法呢?

先看一下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。而且这样做方便以后调试。你模拟多少数据都可以通过这个光驱放进去。

以上纯属个人理解,有什么错误虚心求教。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43299461/article/details/86490341