自解代理模式

为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。

http://www.cnblogs.com/shijiaqi1066/p/4762995.html

 

 

 

代理模式:为对象提供一种代理,以控制对这个对象的访问。

代理模式的作用:

  1. 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
  2. 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
  3. 高扩展性。

 

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

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

 

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

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

posted @ 2015-08-27 13:08  LaplaceDemon  阅读(225)  评论(0编辑  收藏  举报