代理模式
</br>
介绍
代理模式也称委托模式。何谓代理模式?其实代理在我们日常生活中也并不少见,舍友叫你帮他买外卖也是一种代理 ,碰到辞职老板不发工资,那么请个律师帮你打官司,也是一种代理。总而言之,也许你并不留意,但是代理的确无处不在,现实生活中如此,我们的Code世界也是如此!既然如此,小菜我今天来深看下代理模式到底多普遍。
</br>
定义
为其他对象提供一种代理以控制对这个对象的访问
</br>
使用场景
当无法或者不想直接访问某个对象或者访问某个对象存在困难时可能通过一个代理对象来间接访问,为了保护客户端使用的透明性,委托对象与代理对象需要实现相同的接口
</br>
热身demo
买东西的抽象类:
public abstract class BuyFood {
/**
* 一个买的方法
*/
public abstract void buy();
}
我要买外卖,所以,我要实现上面的抽象类,重写里面的方法:
public class MineBuyFood extends BuyFood {
/**
* MineBuyFood中buy的实现具体逻辑
*/
@Override
public void buy() {
System.out.println("我要一份外卖");
}
}
但是,我没空,比较忙,叫舍友帮我买一份外卖,他就成了代理角色,也要继承上面的抽象类,重写里面的方法:
public class ClassMateBuyFood extends BuyFood {
//持有MineBuyFood的引用(可以想象成,我把钱给他,他帮我买外卖)
private MineBuyFood mineBuyFood;
public ClassMateBuyFood(MineBuyFood mineBuyFood) {
this.mineBuyFood = mineBuyFood;
}
@Override
public void buy() {
/**
* 通过引用mineBuyFood的对象调用
*/
mineBuyFood.buy();
}
}
入口类:
/**
* Created by Jenchar on 2016/7/31.
*/
/**
* 好比如,首先把我要买外卖这个类new出来,我再给钱我同学的同时,把我同学帮我买外卖这个类new出来,
* 然后调用方法,即是我同学帮我买外卖这个行为
*
* 我买外卖就是一个真实主题类,我同学帮我买外卖就是一个代理类,他的职责就是帮我买外卖。
*/
public class EnterBuyFood {
public static void main(String[] args) {
/**
* 构造一个MineBuyFood对象
*/
MineBuyFood mineBuyFood=new MineBuyFood();
/**
* 构造一个MineBuyFood对象一个ClassMateBuyFood对象
*/
ClassMateBuyFood classMateBuyFood=new ClassMateBuyFood(mineBuyFood);
/**
* 调用ClassMateBuyFood的方法
*/
classMateBuyFood.buy();
}
}
输出结果:
我要一份外卖
</br>
红牛,再来一缺罐
小菜我上了好久的班 ,老板就是迟迟不发我工资,我也跟他商议了,但他就是有钱不发给我,我怒了,我要告他。
诉讼接口类:
public interface LawsuitImpl {
/**
* 提交申请
*/
void submit();
/**
* 进行举证
*/
void burden();
/**
* 开始辩护
*/
void defend();
/**
* 诉讼完成
*/
void finish();
}
具体诉讼人,Jenchar:
/**
* Created by Jenchar on 2016/7/31.
*/
public class Jenchar implements LawsuitImpl {
@Override
public void submit() {
System.out.println("老板欠我工资");
}
@Override
public void burden() {
System.out.println("这就是证据");
}
@Override
public void defend() {
System.out.println("证据在这里很明显了,投降吧。");
}
@Override
public void finish() {
System.out.println("诉讼成功,还我工资了");
}
}
代理律师类:
/**
* Created by Jenchar on 2016/7/31.
*/
public class ProxyLawyer implements LawsuitImpl{
private Jenchar jenchar;
public ProxyLawyer(Jenchar jenchar) {
this.jenchar = jenchar;
}
@Override
public void submit() {
jenchar.submit();
}
@Override
public void burden() {
jenchar.burden();
}
@Override
public void defend() {
jenchar.defend();
}
@Override
public void finish() {
jenchar.finish();
}
}
法庭类:
/**
* Created by Jenchar on 2016/7/31.
*/
public class Client {
public static void main(String[] args) {
//构造我自己Jenchar
Jenchar jenchar=new Jenchar();
ProxyLawyer proxyLawyer=new ProxyLawyer(jenchar);
//律师帮我提交申请
proxyLawyer.submit();
//律师帮我进行举证
proxyLawyer.burden();
//律师帮我进行辩护
proxyLawyer.defend();
//律师完成我的诉讼
proxyLawyer.finish();
}
}
输出结果:
老板欠我工资
这就是证据
证据在这里很明显了,投降吧。
诉讼成功,还我工资了
</br>
小分析
讲了这么多,上面就说了代理模式的一半,因为代理模式,分为静态代理,动态代理,上面讲得就是静态代理。
看看上面的代码,想一下,上面的充当代理角色的有,小菜我舍友,小菜聘请的律师,其实,我舍友会帮更多的人买外卖,律师被更多的人聘请来打官司,而具体到底是代表哪个人,这就要看代理类中所持有的实际对象(上面就demo,在代理类中持有的真实对象是ClassMate,还有Jenchar),这样,我们引进了一个动态代理,而它不知道要为谁代理。Java给我们提供一个动态代理接口,这个接口名,要死记硬背的,它的名字就是InvocationHandler,里面有一个方法名pulbic Object invoike(Object arg,Method arg1,Object[] arg2),实现该借口并重写该方法就行了,讲这么多,我们来看下Demo
</br>
动态代理
上面的demo就改两个类,一个法庭类,一个代理律师类
代理律师类:
public class ProxyLawyer implements InvocationHandler{
//因为不知道代理谁,所以把他声明一个Object对象
private Object object;
public ProxyLawyer(Object object) {
this.object = object;
}
/**
* 实现该方法,实现动态代理的前戏
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result=method.invoke(object,args);
return result;
}
}
法庭类:
public class Client {
public static void main(String[] args) {
//构造我自己Jenchar
Jenchar jenchar=new Jenchar();
//构造一个动态代理
ProxyLawyer proxyLawyer=new ProxyLawyer(jenchar);
//获取被代理类Jenchar的ClassLoader
ClassLoader loader=jenchar.getClass().getClassLoader();
//动态构造一个代理律师
LawsuitImpl lawsuit=(LawsuitImpl) Proxy.newProxyInstance(loader,new Class[]{LawsuitImpl.class},proxyLawyer);
//律师帮我提交申请
lawsuit.submit();
//律师帮我进行举证
lawsuit.burden();
//律师帮我进行辩护
lawsuit.defend();
//律师完成我的诉讼
lawsuit.finish();
}
}
小传送门:classloader
</br>
小结
静态代理与动态代理,其实,个人觉得比较倾向动态代理,代码解耦,根据不需要考虑去代理谁,高端大气上档次,不过,静态代理比较符合OOP。但是,我还是比较货币动态代理。
</br>
喜欢我的朋友,可以与我一起讨论问题,我也是学习者,希望与大学一起学习。