java设计模式---(3)代理模式

代理模式就是这个事情是A的,A自己不做就B去代他做。代理模式分2种情况:简单的静态代理和稍微复杂的动态代理。

  • 静态代理

实例:
有个老师:

public class Teacher {
	public void teach(String teach) {
		System.out.println("我是老师我在讲课,讲:" + teach);
	}
}

有个助教:

public class Assistant {
	public void beforeTeach(){
		System.out.println("我是助教,讲课前 老师要我帮他 备课");
	}
	
	public void afterTeach(){
		System.out.println("我是助教,讲课后 老师要我帮他 收作业");
	}
}

之前这个老师在学校上课都是上课铃响了再颠进来,直接开口就讲,讲完就闪人的。现在学校规则变了,要求讲课前要先备课,讲课后要学生交作业,老师收作业。但是这个老师他不爱备课呀,布置了作业也不爱批改呀,怎么办呢,这里就只能请个助教,再整个新的上课模式-----代理上课了:

public class TeachProxy {

	private Teacher teacher;
	
	private Assistant assistant;
	
	TeachProxy(Teacher teacher,Assistant assistant){
		this.teacher = teacher;
		this.assistant = assistant;
	}
	
	public void teach(String teach){
		assistant.beforeTeach();
		teacher.teach(teach);
		assistant.afterTeach();
	}
}

在代理上课模式中,上课还是这个老师上,而课前课后的这些他不爱干的事情就都给助教了。所以现在的上课方式就是这样的:

public class MainTest {
	public static void main(String[] args) {
		TeachProxy tp = new TeachProxy(new Teacher(), new Assistant());
		tp.teach("《大学》");
	}
}

输出:

我是助教,讲课前 要我 备课
我是老师我在讲课,讲:《大学》
我是助教,讲课后 要我 收作业

上面就是代理模式的基本思路,A(老师)不自己去做事(自己new Teacher对象,调用teach()方法),而是把事情代理给B(TeachProxy )去做,然后B在帮A做事的时候就可以自己插入一些额外的操作。

再简化一点代理模式可以写成这样:

public class TeachProxy {
	private Teacher teacher;
	
	TeachProxy(Teacher teacher){
		this.teacher = teacher;
	}
	public void teach(String teach){
		teacher.teach(teach);
	}
}

public class MainTest {
	public static void main(String[] args) {
		TeachProxy tp = new TeachProxy(new Teacher());
		tp.teach("《大学》");
	}
}

不要助教了,就是代理类TeachProxy来代老师类来调用这个teach()方法,当然一般都不会这样写,代理类的作用与被代理类完全一样是那不就不用代理了,所以一般都会在代理的过程中去加点什么,这里只是便于理解。

  • 动态代理
    用jdk的动态代理,具体就是要用到java.lang.reflect.Proxy这个类。用这个来实现上面的那个只愿意讲课的老师把他的课前课后的事都甩给助教。老师和助教的2个类都不变,另外还要将老师这个类抽象出一个接口出来:
public interface ITeacher {
	void teach(String teach);
}

下面是代理类:

public class ProxyDynamic implements InvocationHandler {

	private Object A; // 被代理的类,这里一会就是Teacher
	
	private Object C; // 插入的类 , 这里一会就是Assistant

	ProxyDynamic(Object a,Object c) {
		this.A = a;
		this.C = c;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		C.getClass().getDeclaredMethod("before").invoke(C); // 执行助教的方法
		Object invoke = method.invoke(this.A, args); // 执行代理类,也就是老师的方法
		C.getClass().getDeclaredMethod("after").invoke(C); // 执行助教的方法
		return invoke;
	}

}

这里代理类实现了一个接口java.lang.reflect.InvocationHandler然后override了他的invoke()方法,正是这个invoke()方法来帮助代理的类来执行类里面的方法(这里就是Teacher类中的teach()方法)。
下面是调用:

	public static void main(String[] args) {
		Teacher t = new Teacher(); // 老师--被代理的对象
		Assistant a = new Assistant(); // 助教--代理类中做点其他什么事的对象
		InvocationHandler handler = new ProxyDynamic(t, a); // 自己定义的代理
		ITeacher teacher = (ITeacher) Proxy.newProxyInstance(t.getClass().getClassLoader(),
				t.getClass().getInterfaces(), handler);
		teacher.teach("《大学》");
	}

输出跟上面的一样:

我是助教,讲课前 要我 备课
我是老师我在讲课:《大学》
我是助教,讲课后 要我 收作业

大概的说明一下newProxyInstance方法:
newProxyInstance方法
接口说明:返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。3个参数分别是:
loader:代理类的类加载器
interfaces:代理类的接口列表
h:自己定义的handler,用于方法调用
返回值:返回一个指定了方法调用的handler的代理类实例,这个代理类指定了类加载器并且实现了指定的具体接口。说白了就是返回一个代理类的实例,这个实例的三个参(类加载器、代理类的接口列表、handler)数都要指定好。

猜你喜欢

转载自blog.csdn.net/u012843361/article/details/84944113