`

《设计模式》之七:代理模式

阅读更多

Proxy Pattern 代理模式,也叫委托模式 是一个使用率非常高的模式,非常典型的场景就是游戏代练,代练者就是一个代理者或者委托者。其定义如下:

Provide a surrogate or placeholder for another object to control access to it

主要是三个角色:

1,Subject抽象主题角色,可以是抽象类也可以是接口

2,RealSubject具体主题角色,也叫被委托角色、被代理角色,他才是真正的业务逻辑具体执行者

3,Proxy代理主题角色,也叫委托类、代理类,负责对真实角色的应用

 

通用源代码:

/**
 * 抽象主题类
 *
 * @author XiongNeng
 * @version 1.0
 * @since 13-5-23
 */
public interface Subject {
    // 定义一个方法
    void request();
}

 

一个实现类:

public class RealSubject implements Subject {
    @Override
    public void request() {
        // 核心业务逻辑
    }
}

 

代理类:

public class Proxy implements Subject  {
    private Subject subject = null;
    public Proxy() {
        this.subject = new RealSubject();
    }
    public Proxy(Subject subject) {
        this.subject = subject;
    }
    @Override
    public void request() {
        before();
        this.subject.request();
        after();
    }

    // 预处理
    private void before() {
        System.out.println("before");
    }

    // 后处理
    private void after() {
        System.out.println("after");
    }
}

 

代理模式的优点:

1,职责清晰

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

2,高扩展性

具体主题随时会发生变化,只要它实现了接口,甭管它如何变化,都逃不出接口手掌,那么代理类完全可以不做任何修改下使用

3,智能化

动态代理你会看到的,Spring AOP是典型和经典的动态代理模式

 

代理是有个性的

一个类可以实现多个接口,完成不同的整合。也就是说代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上做增强,这种增强的本质通常是对目标对象的方法进行拦截和过滤。例如游戏代理是要收费的,升级一级要5元钱,这个计算功能就是代理类的个性,它应该在代理的接口中定义。

public interface IProxy {
	// 计算费用
	public void count();
}

 

public class GamePlayerProxy implements IGamePlayer, IProxy {
	private IGamePlayer gamePlayer = null;
	// 通过构造函数传递对谁进行代练
	public GamePlayerProxy(IGamePlayer _gamePlayer) {
		this.gamePlayer = _gamePlayer;
	}

	// 代练杀怪
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	// ....省略其他方法

	// 代练升级
	public void upgrade() {
		this.gamePlayer.upgrade();
		count();
	}

	// 计算费用,这个是代理类的提供的功能
	public void count() {
		System.out.println("升级总费用是:200元");
	}

}

 

代理类可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等功能。当然一个代理类,可以代理多个真实角色,并且真实角色之间可以有耦合关系。

 

>>> 动态代理:

最后是我们的压轴大戏动态代理

动态代理在实现阶段不用关系代理谁,而是在运行阶段才指定代理哪一个对象。

InvocationHandler是JDK提供的动态代理接口,对被代理的方法进行代理。

public class GamePlayerIH implements InvocationHandler {
	// 被代理者
	Class cls = null;
	// 被代理的实例
	Object obj = null;
	// 我要代理谁
	public GamePlayerIH(Object _obj) {
		this.obj = _obj;
	}
	// 调用被代理的方法
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = method.invoke(this.obj, args);
		return result;
	}
}

 通过InvocationHandler接口,所有的方法都由Handler来进行处理,invoke方法为必须实现的方法。

下面是一个简单的场景使用:

public class Client {
	public static void main(String[] args) {
		// 定义一个痴迷玩家
		IGamePlayer player = new GamePlayer("张三");
		// 定义一个Handler
		InvocationHandler handler = new GamePlayerIH(player);
		// 开始打游戏
		System.out.println("开始时间是: 2013-05-23 12:34");
		// 获得类的class loader
		ClassLoader cl = player.getClass().getClassloader();
		// 动态产生一个代理者
		IGamePlayer proxy = (IGamePlayer)proxy.newProxyInstance(cl, new Class[] {IGamePlayer.class}, handler);
		// 登录
		proxy.login("zhangsan", "password");
		// 开始杀怪
		proxy.killBoss();
		// 升级
		proxy.upgrade();
		// 记录结束时间
		System.out.println("结束时间是:2013-05-24 11:10");
	}
}

 

别急,动态代理最强大的地方是注入,如果上面的游戏玩家每次登陆后需要发一个信息给我吗,防止账号被盗,直接修改GamePlayer不是个好方法。

public class GamePlayerIH implements InvocationHandler {
	// 被代理者
	Class cls = null;
	// 被代理的实例
	Object obj = null;
	// 我要代理谁
	public GamePlayerIH(Object _obj) {
		this.obj = _obj;
	}
	// 调用被代理的方法
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = method.invoke(this.obj, args);
		// 如果是登录方法,则发送信息
		if (method.getName().equalsIgnoreCase("login")) {
			System.out.println("账号登录了");
		}
		return result;
	}
}

 

AOP编程没有使用什么新的技术,但是它对我们的设计、编码有非常大的影响,对于日志、事务、权限等都可以在系统设计阶段不同考虑,而在设计后通过AOP的方式切过去。

 

于是我们知道,一个类的动态代理类是这样一个类,由InvocationHandler的实现类实现所有的方法,由其invoke方法接管所有方法的实现。

 

一个简单的AOP框架,可以在此基础上进行扩展:

抽象主题类Subject:

/**
 * 抽象主题类
 *
 * @author XiongNeng
 * @version 1.0
 * @since 13-5-23
 */
public interface Subject {
    // 定义一个方法
    void request();
}

 真实主题:

/**
 * 真实主题
 *
 * @author XiongNeng
 * @version 1.0
 * @since 13-5-23
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        // 核心业务逻辑
    }
}

 动态代理的Handler类:

public class MyInvocationHandler implements InvocationHandler {
	// 被代理的实例
	Object obj = null;
	// 我要代理谁
	public GamePlayerIH(Object _obj) {
		this.obj = _obj;
	}
	// 调用被代理的方法
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = method.invoke(this.obj, args);
		return result;
	}
}

 动态代理类:

public class DynamicProxy<T> {
	public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
		// 寻找JoinPoint连接点,AOP框架使用元数据定义
		if (true) {
			// 执行一个前置通知
			(new BeforeAdvice()).exec();
		}
		// 执行目标,并返回结果
		return (T) Proxy.newProxyInstance(loader, interfaces, h);
	}
}

 

上面的DynamicProxy只是一个通用的类,不具有业务含义,我们可以实现一个具有业务含义的动态代理类

public class SubjectDynamicProxy extends DynamicProxy {
	public static <T> T newProxyInstance(Subject subject) {
		// 获得Classloader
		Classloader loader = subject.getClass().getClassLoader();
		// 获得接口数组
		Class<?>[] classes = subject.getClass().getInterfaces();
		// 获得handler
		InvocationHandler handler = new MyInvocationHandler(subject);
		return newProxyInstance(loader, classes, handler);
	}
}

 

这样一来,使用起来就非常简单了。

 

最佳实践:

代理模式使用非常广泛,大到系统框架、企业平台,小到代码片段、事务处理,稍不留意就用到代理模式。

有了Spring AOP 和 AspectJ这样优秀的工具,就更不用讲了。

 

AOP框架中,有几个概率一定要弄清楚:

切面 Aspect

切入点 JoinPoint

通知 Advice

织入 Weave

这几个概率请参考我的另一篇文章:

http://yidao620c.iteye.com/blog/1837689

 

本人博客已搬家,新地址为:http://yidao620c.github.io/

分享到:
评论

相关推荐

    Java 经典设计模式讲解以及项目实战

    8 代理模式 9 装饰模式 10 原型模式 11 委派模式 12 适配器模式 设计模式综合运用 1 门面+模版方法+责任链+策略 2 门面+模版方法+责任链+策略+工厂方法 3 动态代理+Spring AOP 4 责任链模式进阶 Spring Framework...

    设计模式:可复用面向对象软件的基础(非扫描版+高清)

    设计模式分为三类:创建型模式(如单例模式、工厂方法模式)、结构型模式(如代理模式、装饰器模式)和行为型模式(如观察者模式、策略模式)。每种模式都有其特定的用途和适用场景。 4. **具体设计模式详解** - ...

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    设计模式:可复用面向对象软件的基础.zip

    设计模式是软件工程中的一种重要概念,它代表了在特定情境下解决常见问题的最佳实践。这些模式经过时间的考验,被广泛应用于各种面向对象的软件开发中,以提高代码的可读性、可维护性和可复用性。本教程旨在深入讲解...

    设计模式之代理模式demo

    代理模式是一种常用的设计模式,它在软件开发中起到了中介或者代表的作用。代理模式的主要目的是为其他对象提供一种代理以控制对这个对象的访问。通过引入代理,我们可以增加新的功能,如缓存、日志记录、访问控制等...

    软件体系结构实验报告--设计模式2

    本实验报告主要探讨了五个关键的设计模式:组合模式、外观模式、代理模式、观察者模式以及策略模式,这些都是软件体系结构中的重要组成部分,对于理解和优化代码结构具有深远影响。 1. **组合模式**: 组合模式是一...

    23种设计模式之:建造者,代理,观察,策略,状态模式

    本文将重点介绍标题中提到的五种设计模式:建造者模式、代理模式、观察者模式、策略模式以及状态模式。 **1. 建造者模式(Builder)** 建造者模式是一种创建型设计模式,它允许我们分步骤构建复杂对象,而无需暴露...

    设计模式之代理模式

    **设计模式之代理模式** 代理模式是软件设计模式中的一种结构型模式,它在对象交互过程中引入一个代理,代理对象负责控制对原对象的访问。这种模式的主要目的是为了解耦,提供一种替代真实对象的方式,使得客户端...

    php设计模式案例详解

    18. **代理设计模式**:为其他对象提供一种代理以控制对这个对象的访问。 19. **工厂方法设计模式**:定义一个创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。 20. **适配器...

    JAVA设计模式chm文档

    设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...

    C#设计模式(设计模式的思想:对通用的对象间的相互作用方式进行记录和编目)

    8. **代理模式**:为其他对象提供一种代理以控制对这个对象的访问,常用于远程代理、虚拟代理和保护代理等场景。 9. **享元模式**:用于节省内存空间,通过共享大量细粒度对象来减少系统中对象的数量。 10. **状态...

    设计模式-代理模式

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色,特别是在iOS平台的应用程序设计中。代理模式的核心思想是为一个对象提供一个替身或代理,以控制对这个对象的访问。这种模式允许我们通过代理来间接...

    java之23种设计模式完整代码

    这里我们探讨的“Java之23种设计模式完整代码”是一份宝贵的资源,它包含了所有23种经典设计模式的实现示例。这份资料能够帮助开发者深入理解每种设计模式的概念、应用场景以及它们之间的差异。 设计模式是经过时间...

    JAVA设计模式之代理模式实例

    代理模式是设计模式的一种,它提供了一种对目标对象进行增强或者控制访问的方式。在本实例中,我们将深入探讨Java中的代理模式及其应用。 代理模式的核心思想是为一个对象创建一个代理对象,这个代理对象在客户端和...

    《设计模式:可复用面向对象软件的基础》英文版

    《设计模式:可复用面向对象软件的基础》是一本由Erich Gamma、Richard Helm等四位国际知名的软件工程师共同编写的经典之作,该书提供了面向对象软件设计中常用的模式,并通过具体的案例解释了这些模式如何帮助解决...

    23种设计模式详解PDF

    适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式(11): 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、...

    Java设计模式之代理模式(结构)

    ### Java设计模式之虚拟代理模式详解 #### 一、引言 在软件工程领域,设计模式作为一种被广泛接受的最佳实践,对于提高代码质量和可维护性起着至关重要的作用。其中,“代理模式”作为结构型设计模式之一,在解决...

    设计模式之美——教你写出高质量代码

    "设计模式之美——教你写出高质量代码"这个主题旨在帮助开发者更好地理解和应用设计模式,从而提升代码的质量和可维护性。设计模式不仅对面试有所帮助,也是职场发展中的必备技能,无论你使用哪种开发语言。 设计...

    .net实现设计模式之代理模式

    代理模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,特别是在.NET框架下。代理模式的核心思想是为一个对象提供一个替代品或代表,这个替代品能够控制对原对象的访问,使得客户端代码可以通过代理对象与...

Global site tag (gtag.js) - Google Analytics