为什么使用代理模式?
先举个栗子:
Worker的职责是工作:
public interface Worker {//工人
void work();//工作
}
而Worker又分很多类型,比如说医生,教师,程序员…
就拿医生来说:
public class Doctor implements Worker {
@Override
public void work() {
cure();//医生工作是治病
}
private void cure() {
Log.e("TAG", "Doctor is working");
}
}
调度程序:
public class ScheduleHandler {
public static void startWork() {
new Doctor().work();
}
}
Worker开始工作:
public void main(String[] args) {
ScheduleHandler.startWork();
}
Worker的一次工作完成了.
现在要给Doctor增加一个签到功能,我们可以在Doctor中直接增加一个签到功能,但是如果我们要给所有职业的Worker都增加签到的功能,是不是要给所有Worker(如:Teacher,Programmer,Designer…)中都增加相同的代码呢,这样做确实可以达到目的,但是增加了大量重复的代码,这时就可以使用代理模式了.
Worker的代理类:
public class ProxyWorker implements Worker {
private Worker worker;
public ProxyWorker(Worker doctor) {
this.worker = doctor;
}
@Override
public void work() {
signIn();//签到
worker.work();
}
private void signIn() {
Log.e("TAG", "Worker signed in");
}
}
我们的调度程序需要做出改变:
public class ScheduleHandler {
public static void startWork() {
new ProxyWorker(new Doctor()).work();
}
}
Worker开始工作:
public void main(String[] args) {
ScheduleHandler.startWork();
}
这样我们给Doctor增加了签到的功能,而且其他职业的Worker(如:Teacher,Programmer,Designer…)也可以使用ProxyWorker来实现签到的功能,代理模式是不是大大减少了我们的代码量,这就是我们为什么要使用代理模式的原因了.
为什么使用动态代理模式
还是接着上面的例子,现在有Student(与Worker同级)也需要一个签到的功能
public interface Student {
void study();
}
初中生:
public class Junior implements Student {
@Override
public void study() {
Log.e("TAG", "Junior is stutying");
}
}
如果按照上面ProxyWorker的思想,我们可以再写一个ProxyStudent来代理所有级别Student(如:小学生,初中生,高中生…),并在ProxyStudent中加入签到的方法,可如果我们还想更省事些怎么办?这时就可以使用动态代理了:
class ProxyHandler implements InvocationHandler {
private Object tartget;
public ProxyHandler(Object doctor) {
this.tartget = doctor;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("work".equals(method.getName())) {
Log.e("TAG", "worker signed in");
}
if ("study".equals(method.getName())) {
Log.e("TAG", "student signed in");
}
return method.invoke(tartget, args);
}
}
invoke中,我们根据方法名来区别是Worker还是Student做签到的动作
分别让Student,Worker去签到学习/工作:
public void main(String[] args) {
Student junior = new Junior();
InvocationHandler handler1 = new ProxyHandler(junior);
Student student = (Student) Proxy.newProxyInstance(
junior.getClass().getClassLoader(), junior.getClass().getInterfaces(), handler1);
student.study();
Worker doctor = new Doctor();
InvocationHandler handler2 = new ProxyHandler(doctor);
doctor.getClass().getClassLoader(), doctor.getClass().getInterfaces(), handler2);
worker.work();
}
打印结果:
TAG: student signed in
TAG: Junior is stutying
TAG: worker signed in
TAG: Doctor is working
上例中我们可以发现,通过动态代理我们可以动态的获取到方法名,还有代理类的实例,当然动态代理能获取都的信息不仅仅是这些,通过动态代理的能够动态获取信息的特性,我们就可以完成一些特殊的操作.