`
goalietang
  • 浏览: 25923 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

浅谈设计模式2 -- 代理模式

阅读更多
        说到代理模式,我想从字面意思,应该是最容易理解的吧。就是本来该我做的事情,我让别人帮我代做了,我不去管别人怎么做,或者说别人做的时候开始会不会多做点什么,结束会不会多做点什么。反正我只知道,我交代做的事情要一件不差的给我代办好。

        举个例子,火车票代购,我事情太多,要找个人代我去买一张火车票。反正我把钱给他了,我的目的就是得到一张票,我管你是偷是抢还是怎样去帮我搞到票。可能你帮我买票之前,会去查一下网上买得到不,找一下有没有人有这方面的推荐...我不管你之前要多干些神马东西。然后你买到票了后,可能你要感谢一下帮你淘到票的人,又可能会记录一下你买票的心得。我也懒得理你,反正到最终你得给我一张我要的火车票。

        以上是代理模式的生活化的一种介绍,在说说在我们程序员这个层面的介绍。那就是:一个角色代表另一个角色来完成某些特定的功能。代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

        先说点题外话,我们要让一个角色帮助(代表)另外一角色来完成一个特定功能(也可以说成执行一个特定方法),其实有几种实现方法,我们来看看最常想到的方法:
        定义一个类SimpleMe,这个类里面有个需要执行的方法doSometing:
public class SimpleMe {
	public void doSometing(){
		System.out.println("do someting........");
	}
}

       再写一个类,继承这个类,重写这个方法,然后呢...
public class OtherProxyMe extends SimpleMe {
	@Override
	public void doSometing() {
		System.out.println("help you to do before");
		super.doSometing();
		System.out.println("help you to do after");
	}
}

        很简单,继承了这个类,重写了这个方法,然后在这个方法里面调用父类的相同方法,最后再调用前后加上自己额外做的事情。可是仔细想想这样的代码会有什么问题呢?首先,滥用了java的继承,单一继承不是这么就浪费掉的。其次继承这种方式依赖性太大。修改父类,第一影响到的就是子类。

        再来看另一种“组合”方式的实现方法,这里我们只写代理类,原始类相同
public class OtherProxyMe {
	private SimpleMe sm;
	public OtherProxyMe(SimpleMe sm){
		this.sm = sm;
	}
	public void doSometing() {
		System.out.println("help you to do before");
		sm.doSometing();
		System.out.println("help you to do after");
	}
}

        这里我们是让这个代理对象拥有原始对象,然后在代理对象执行doSometing()方法的时候顺便执行以下原始对象的doSometing()方法,组合的好处不言而喻,可是以上的代码还是存在问题。首先,代理对象中任何方法都可以执行原始对象的doSomething()方法,我怎么知道是哪个方法在做代理的事情。也可能这个执行原始对象方法的是abc()方法,又可能是def()方法。我们需要规范一下,doSomething()就是doSomething()。原始类要做doSomething(),那么代理类就必须是做doSomething()。而不是abc(),def()。那怎么规范呢?就是让代理对象和原始对象都实现同一个接口。让他们都必须重写doSomething()方法。这样一来,代理对象就名正言顺的使用doSomething()来代理原始对象的doSomething()了。
//定义一个代理接口
public interface SimpleInterface {
	public void doSometing();
}
//原始对象(被代理对象)
public class SimpleMe implements SimpleInterface{
	
	public void doSometing(){
		System.out.println("do someting........");
	}
}
//代理对象
public class OtherProxyMe implements SimpleInterface{
	private SimpleMe sm;
	public OtherProxyMe(SimpleMe sm){
		this.sm = sm;
	}
	public void doSometing() {
		System.out.println("help you to do before");
		sm.doSometing();
		System.out.println("help you to do after");
	}
}

        虽然代理对象比起上面的代码,只是多实现了一个跟原始对象相同的接口,其他的任何地方doumeiy偶改变,但是这样就做了一个很好的规范。使代理方法代理原始方法顺理成章。而且,用组合比用继承好,你稍稍理解一点设计原则都会知道。

        以上,就是是一个简单的静态代理模式的实现,对,你没有听错,你已经学会了一个简单的代理模式了。你可以勇于实践,比如说我执行一个数据库操作,将获取数据库连接和关闭连接资源让代理类来实现,我原始类只focus业务,就是我的数据库操作。又或者,我需要在方法前后加点log,这样的简单代理都能实现。

        再来说说动态代理,很多框架技术用到了动态代理,什么是动态代理呢?

        静态代理由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。而动态代理是在程序运行时,代理类运用反射机制动态创建而成。动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。我们来看看实现:
public class MyHandler implements InvocationHandler {
	//组合一个原始对象
    private Object target;
    //构造方法注入原始对象
    public MyHandler(Object t){
    	this.target = t;
    }
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		//执行原始方法之前,执行一些其他方法
		MyProxyMethod.executeBegin(target.getClass().getName() +"."+ method.getName());
		//通过反射执行原始方法
		Object bj = method.invoke(target, args);
		//执行原始方法之后,执行一些其他方法。
		MyProxyMethod.executeEnd(target.getClass().getName() +"."+ method.getName());
		//返回执行结果。
		return bj;
	}
}

       上面就是个基本的动态代理Handler的写法。只需要写这个类,然后有个原始类,我们来看下面的测试方法,如何实现动态代理。
	public static void main(String[] args) {
		//new一个原始对象
		Business a = new BusinessA();
		//将原始对象注入到handler
		MyHandler m = new MyHandler(a);
		//获取代理对象,这里是使用了Proxy的newProxyInstance方法
		Business proxy 
		= (Business) Proxy.newProxyInstance(a.getClass().getClassLoader(), 
				a.getClass().getInterfaces(), m);
		//执行代理方法
		proxy.b1();
		proxy.b2();
	}

        我们在newProxyInstance的时候,传入了三个参数,第一个就是原始对象的ClassLoader,第二个参数是代理对象的接口类型,因为我们知道代理对象和原始对象应该实现同一个接口,这里获取的接口也是原始对象的接口,最后一个参数就是我们自己定义的Handler。这样子,我们就实现了一个动态代理方法。

        顺便说一下,Spring的AOP也是使用InvocationHandler方式来实现的。

        (非常注意点:因为是完全的面向接口编程,所以使用动态代理的时候,所有对象初始化都采用动态绑定方式,用其接口类型来获得实际类型,否则运行时会报错。)
分享到:
评论

相关推荐

    从追MM浅谈Java的23种设计模式

    2. 结构型设计模式: - 适配器模式:将两个不兼容的接口转换为可以互相操作的接口。 - 桥接模式:将抽象部分与实现部分分离,使它们可以独立变化。 - 组合模式:允许你将对象组合成树形结构,可以以统一的方式...

    C#面向对象设计模式纵横谈 12种设计模式

    在编程领域,设计模式是解决常见问题的经过验证的、可重用的解决方案。...通过阅读《C#面向对象设计模式纵横谈》一书,你将能够深入了解这些模式的实现细节和应用场景,从而在实际开发中游刃有余。

    java之浅谈深说--教你如何成长

    ### Java之浅谈深说——教你如何成长为Java编程高手 在IT行业中,Java作为一种广泛使用的编程语言,其重要性不言而喻。对于希望成为Java编程高手的学习者来说,掌握正确的学习路径至关重要。本文将根据提供的标题、...

    浅谈Java设计模式系列-装饰器模式

    Java 设计模式系列 - 装饰器模式 Java 设计模式系列 - 装饰器模式是 Java 设计模式系列中的一种重要模式,它主要用于对目标方法进行增强,提供新的功能或者额外的功能。装饰器模式的主要特点是涉及的是单方,目标...

    浅谈OOP之uml设计模式

    **OOP之UML设计模式概述** 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它以对象为中心,强调数据和操作数据的方法,通过封装、继承和多态等特性来实现软件的模块化和可扩展性。在OOP中...

    漫谈设计模式代码

    《漫谈设计模式》这本书深入浅出地介绍了多种设计模式,通过代码实例帮助读者理解和应用这些模式。在这个压缩包“ramblingonpatterns-1.0”中,你将找到书中的代码示例,它们覆盖了各个章节的关键知识点。 1. **...

    浅谈C#设计模式之代理模式

    代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口.根据代理模式的...

    浅谈JAVA设计模式之代理模式

    JAVA设计模式之代理模式 代理模式是结构型模式之一,它主要解决了直接访问对象时带来的问题,如对象创建开销很大、某些操作需要安全控制、需要进程外的访问等。代理模式的目的是提供一种代理,以控制对这个对象的...

    浅谈java代理机制 .txt

    ### 浅谈Java代理机制 #### 一、引言 在深入探讨Java代理机制之前,我们首先需要了解代理模式的基本概念及其应用场景。代理模式是一种结构型设计模式,它为其他对象提供了一种代理以控制对这个对象的访问。在Java...

    浅谈spring中用到的设计模式及应用场景

    浅谈Spring中用到的设计模式及应用场景 Spring 框架是 Java 企业级应用程序的核心组件之一,它提供了强大的功能和灵活的架构来简化企业级应用程序的开发。Spring 框架使用了多种设计模式来实现其功能,本文将对 ...

    design-pattern-java.pdf

    实现对象的复用——享元模式(二) 实现对象的复用——享元模式(三) 实现对象的复用——享元模式(四) 实现对象的复用——享元模式(五) 代理模式-Proxy Pattern 设计模式之代理模式(一) 设计模式之代理模式...

    Java 设计模式

    - **从招式与内功谈起**:这部分内容旨在通过比喻的方式,帮助读者理解设计模式的本质及其在实际开发中的应用价值。招式指的是具体的编码技巧,而内功则是对设计模式背后的原理的理解。 #### 三、面向对象设计原则 ...

    C#面向对象设计模式纵横谈(11)

    2. **工厂模式**: 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在C#中,可以定义一个工厂类,用于创建一系列相关的对象,而无需暴露具体的创建逻辑给客户端。 3. **抽象工厂模式**: 这是工厂...

    浅谈观察者模式及在C#中的实现

    观察者模式(Observer Pattern)是一种行为设计模式,其主要目的是解决面向对象设计中常见的问题——如何实现对象间的解耦,使得一个对象的状态改变能够自动通知其他多个依赖对象,从而达到“高内聚、低耦合”的设计...

    访问硬件的设计模式-经验文摘

    在IT行业中,设计模式是一种被广泛认可的解决特定问题或实现特定功能的模板,它在软件工程...通过阅读"嵌入式系统架构浅谈_编程设计模式 (一)---访问硬件的设计模式.html"这篇文章,你可以深入了解这些模式的实践应用。

    浅谈机场管理社会化和管理模式多样化

    例如,代理型管理模式侧重于机场运营的代理和咨询服务,风险型管理模式强调风险分担和控制,设计建造模式(Design-Build)则将设计和建造任务交由同一承包商,这样可以在很大程度上简化流程并缩短工期。BOT模式...

    浅谈人工智能

    计算机视觉包括图像处理和模式识别,自然语言处理涉及语音识别、合成和对话系统,认知与推理包含了模拟人类思维和决策过程的研究,机器人学则聚焦于机器人的设计、控制和规划,博弈与伦理关注多代理系统的交互,而...

    Web_安全架构浅谈.pdf

    在《Web安全架构浅谈》中,主要讨论了Web安全的多个方面,包括安全架构、扫描器、WAF(Web应用防火墙)以及面临的挑战和解决方案。以下是详细的知识点解析: 1. **Web安全扫描器**: - 扫描器用于检测Web应用中的...

Global site tag (gtag.js) - Google Analytics