您的位置:首页 > 其它

自解代理模式

2015-08-27 13:08 274 查看
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/4762995.html
代理模式:为对象提供一种代理,以控制对这个对象的访问。

代理模式的作用:

职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。

高扩展性。

以上的废话都来自百度百科。如果不真正敲代码,是不能真正理解到代理模式的好处的。

实现代理模式比较简单,可代理模式却真正能对代码做出很多有效的扩展,并且可以高效的复用代码。

首先有一个行为接口。该接口用于定义需要代理的动作。

public interface Shopping {
void shopping();
}


试想普通人去超市买东西。一般买东西有个过程,即“去商场”“购物”“回家”。

一般来说,例如有三类人,美女,男生,大妈。他们都要买东西,但买的东西都不同。

class BeautifulGirl implements Shopping {
@Override
public void shopping() {
System.out.println("买鞋子");
}
}

class SchoolBoy implements Shopping {
@Override
public void shopping() {
System.out.println("买玩具");
}
}

class SquareDanceAunt implements Shopping {
@Override
public void shopping() {
System.out.println("买衣服");
}
}


这些买东西的人要买东西,他们都需要先“去商场”最后“回家”。那么就需要扩展以上代码。

传统思路

那么一般“扩展”方法如下:

class BeautifulGirl implements Shopping {
@Override
public void shopping() {
System.out.println("去商场");
System.out.println("买鞋子");
System.out.println("回家");
}
}

class SchoolBoy implements Shopping {
@Override
public void shopping() {
System.out.println("去商场");
System.out.println("买玩具");
System.out.println("回家");
}
}

class SquareDanceAunt implements Shopping {
@Override
public void shopping() {
System.out.println("去商场");
System.out.println("买衣服");
System.out.println("回家");
}
}


现在,我们命令这些人去买东西,执行如下:

public class World {
public static void main(String[] args) {
Shopping beautifulGirl = new BeautifulGirl();
Shopping schoolBoy = new SchoolBoy();
Shopping squareDanceAunt = new SquareDanceAunt();

beautifulGirl.shopping();
schoolBoy.shopping();
squareDanceAunt.shopping();
}
}


这种修改方法违反了开闭原则与DRY原则。

可以直观的感受到,其中以下代码需要重复写,很累。

System.out.println("去商场");
// ......
System.out.println("回家");


静态代理

我们需要给这些人提供一个代理,让代理去简化买东西的过程,把“去商场”,“回家”这个过程却都有代理去做了。

现实中,这种代理一般我们喜欢叫他雷锋。

public class LeiFengProxy implements Shopping {

/**
* 雷锋侠要服务的对象。
*/
private Shopping shoper;

/**
* 召唤雷锋侠。
* @param shoper
*/
public LeiFengProxy(Shopping shoper){
this.shoper = shoper;
}

@Override
public void shopping() {
System.out.println("去商场");
shoper.shopping();
System.out.println("回家");
}

}


有了雷锋这种代理,让这些人去买东西就轻松很多了。

public class World {
public static void main(String[] args) {
Shopping beautifulGirl = new BeautifulGirl();
Shopping schoolBoy = new SchoolBoy();
Shopping squareDanceAunt = new SquareDanceAunt();

Shopping beautifulGirlProxy = new LeiFengProxy(beautifulGirl);
Shopping schoolBoyProxy = new LeiFengProxy(schoolBoy);
Shopping squareDanceAuntProxy = new LeiFengProxy(squareDanceAunt);

beautifulGirlProxy.shopping();
schoolBoyProxy.shopping();
squareDanceAuntProxy.shopping();

}
}


让每个人的代理雷锋去买东西,实际上代理雷锋操作了买东西的这个人,

这种修改精简了代码,不再需要重复写“去商场”“回家”,而且符合开闭原则与DRY。

动态代理

一般动态代理直接使用JDK的动态代理。将与Shopping这个动作的无关的动作直接封装起来。

public class GoShopHandler implements InvocationHandler {

/**
* 服务对象
*/
private Object object;

public GoShopHandler(Object object){
this.object = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("去商场");
method.invoke(object,args);
System.out.println("回家");
return null;
}

}


不再需要写代理类。直接生成代理对象。

public class World {
public static void main(String[] args) {
Shopping beautifulGirl = new BeautifulGirl();
Shopping schoolBoy = new SchoolBoy();
Shopping squareDanceAunt = new SquareDanceAunt();

Shopping beautifulGirlProxy = (Shopping) Proxy.newProxyInstance(beautifulGirl.getClass().getClassLoader(), beautifulGirl.getClass().getInterfaces(), new GoShopHandler(beautifulGirl));
Shopping schoolBoyProxy = (Shopping) Proxy.newProxyInstance(schoolBoy.getClass().getClassLoader(), schoolBoy.getClass().getInterfaces(), new GoShopHandler(schoolBoy));
Shopping squareDanceAuntProxy = (Shopping) Proxy.newProxyInstance(squareDanceAunt.getClass().getClassLoader(), squareDanceAunt.getClass().getInterfaces(), new GoShopHandler(squareDanceAunt));

beautifulGirlProxy.shopping();
schoolBoyProxy.shopping();
squareDanceAuntProxy.shopping();

}
}


使用动态代理中扩展代码与原始对象的接口无关。即动态代理比静态代理的优势在于GoShopHandler可以扩展任意“到商场去”的动作,不一定要局限于Shopping。也有可能有些人去商场是去工作的,比如营业员。

public interface Working {
void working();
}


public class SalesClerk implements Working {
@Override
public void working() {
System.out.println("上班");
}
}


结合GoShopHandler扩展营业员的Working动作。

public class World {
public static void main(String[] args) {
Shopping beautifulGirl = new BeautifulGirl();
Shopping schoolBoy = new SchoolBoy();
Shopping squareDanceAunt = new SquareDanceAunt();
SalesClerk salesClerk = new SalesClerk();

Shopping beautifulGirlProxy = (Shopping) Proxy.newProxyInstance(beautifulGirl.getClass().getClassLoader(), beautifulGirl.getClass().getInterfaces(), new GoShopHandler(beautifulGirl));
Shopping schoolBoyProxy = (Shopping) Proxy.newProxyInstance(schoolBoy.getClass().getClassLoader(), schoolBoy.getClass().getInterfaces(), new GoShopHandler(schoolBoy));
Shopping squareDanceAuntProxy = (Shopping) Proxy.newProxyInstance(squareDanceAunt.getClass().getClassLoader(), squareDanceAunt.getClass().getInterfaces(), new GoShopHandler(squareDanceAunt));
Working salesClerkProxy = (Working) Proxy.newProxyInstance(salesClerk.getClass().getClassLoader(), salesClerk.getClass().getInterfaces(), new GoShopHandler(salesClerk));

beautifulGirlProxy.shopping();
schoolBoyProxy.shopping();
squareDanceAuntProxy.shopping();
salesClerkProxy.working();

}
}


总结一下,代理模式的思想是创建一个代理对象,使用这个对象去操作原始对象(被代理的对象)。从而起到扩展原始对象的动作的目的。并且可以把与原始对象无关的扩展代码抽象到一起去。

代理模式的是AOP的基础,其效果有点像与Windows编程中的Hook技术,只不过这里是面向对象的。

为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/4762995.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: