`
wangwengcn
  • 浏览: 172978 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

6.代理模式(Proxy Pattern)

阅读更多

1.定义:

为其他对象提供一种代理以控制这个对象的访问。
代理模式也叫委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了代理模式。

 

2.代理模式的三个角色定义:

  • Subject抽象主题角色:抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。
  • RealSubject具体主题角色:也叫被委托角色、被代理角色。是业务逻辑的具体执行者。
  • Proxy代理主题角色:也叫委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后工作。(最简单的比如打印日志)

3.代理模式的使用场景:

想想现实世界中,打官司为什么一定要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的答辩就成,其他的比如事前调查、时候追查都由律师来搞定。同理,在我们程序设计中也可是使用代理模式来将由一系列无关逻辑组合在一起的代码进行解耦合,比如业务代码中的日志代码就可以在代理中进行。Spring的AOP就是典型的动态代理应用。

 

4.代理模式的扩展一(普通代理):

普通代理,它的要求是客户端只能访问代理角色,而不能访问真实角色(真实角色在proxy构造方法中创建),我们只要修改一下上面的proxy类就可以了,请看代码:

 

package _6ProxyPattern;

/**
 * 定义一个会玩游戏的人的接口
 * 他必须先登录,然后开始玩游戏
 */
public interface IGamePlayer {

	public void login();
	
	public void play();
	
	public String getUserName();
}

 

package _6ProxyPattern;

import java.util.Date;

/**
 * 这是一个游戏玩家
 */
public class GamePlayer implements IGamePlayer {

	private String userName;
	
	public GamePlayer(String userName)
	{
		this.userName = userName;
	}
	
	@Override
	public void login() {
		System.out.println("玩家:"+userName+"登录了;时间:"+new Date().toString());
	}

	@Override
	public void play() {
		System.out.println("玩家:"+userName+"正在打怪");
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

}
 
package _6ProxyPattern;

/**
 * 我是一个游戏代练
 */
public class ProxyPlayer implements IGamePlayer {
	
	// 这是我要代练的账号
	private IGamePlayer gamePlayer;

	public ProxyPlayer(IGamePlayer gamePlayer)
	{
		this.gamePlayer = gamePlayer;
	}
	
	@Override
	public void login() {
		System.out.println("日志:"+getUserName()+"开始代练"+gamePlayer.getUserName()+"的游戏账号了");
		gamePlayer.login();
	}

	@Override
	public void play() {
		System.out.println("日志:"+getUserName()+"开始给"+gamePlayer.getUserName()+"的游戏账号打怪升级了");
		gamePlayer.play();
	}

	// 代练者也是有名字的
	@Override
	public String getUserName() {
		return "代练者-李四";
	}

}

 

5.代理模式的扩展二(强制代理):

现实中可能会有这样的场景:你去找一个明星帮忙,该明星告诉你他比较忙,要你先联系他的助理(代理),助理然后安排时间,明星才帮你做事情。也就是说你虽然找到了真实角色,真实角色却强制你去寻找代理。
强制代理在设计模式中比较另类,为什么这么说呢?一般的思维都是通过代理找到真实的角色,但是强制代理却要强制你必须通过真实角色查找到代理角色,否则你不能访问。
强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法。代理的管理已经由真实角色自己完成了。
请看代码:

package _6ProxyPattern.forced;

/**
 * 定义一个会玩游戏的人的接口
 * 他必须先登录,然后开始玩游戏
 */
public interface IGamePlayer {

	public void login();
	
	public void play();
	
	public String getUserName();
	
	public IGamePlayer getProxy();
}
 
package _6ProxyPattern.forced;

import java.util.Date;

/**
 * 这是一个游戏玩家
 */
public class GamePlayer implements IGamePlayer {

	private String userName;
	private IGamePlayer proxy;
	
	public GamePlayer(String userName)
	{
		this.userName = userName;
	}
	
	@Override
	public void login() {
		if(isProxy())
		{
			System.out.println("玩家:"+userName+"登录了;时间:"+new Date().toString());
		}else{
			System.out.println("请使用指定的代理");
		}
	}

	@Override
	public void play() {
		if(isProxy())
		{
			System.out.println("玩家:"+userName+"正在打怪");
		}else{
			System.out.println("请使用指定的代理");
		}
	}

	@Override
	public IGamePlayer getProxy() {
		this.proxy = new ProxyPlayer(this);
		return proxy;
	}
	
	private boolean isProxy()
	{
		if(proxy == null)
		{
			return false;
		}
		return true;
	}
	
	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}
}
 
package _6ProxyPattern.forced;

/**
 * 场景类,除了这种方式,别的方式调用将会提示你采用代理方式访问
 */
public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		IGamePlayer gamePlayer = new GamePlayer("张三");
		IGamePlayer proxyPlayer = gamePlayer.getProxy();
		proxyPlayer.login();
		proxyPlayer.play();
	}

}

 

6.代理模式的扩展三(虚拟代理):

虚拟代理很简单,在需要的时候才初始化真实角色对象,可以避免被代理对象较多而引起的初始化缓慢问题。
请看代码:

package _6ProxyPattern;

/**
 * 我是一个游戏代练
 */
public class VirualProxyPlayer implements IGamePlayer {
	
	// 这是我要代练的账号
	private IGamePlayer gamePlayer;

	@Override
	public void login() {
		if(gamePlayer == null)
		{
			gamePlayer = new GamePlayer("张三");
		}
		System.out.println("日志:"+getUserName()+"开始代练"+gamePlayer.getUserName()+"的游戏账号了");
		gamePlayer.login();
	}

	@Override
	public void play() {
		if(gamePlayer == null)
		{
			gamePlayer = new GamePlayer("张三");
		}
		System.out.println("日志:"+getUserName()+"开始给"+gamePlayer.getUserName()+"的游戏账号打怪升级了");
		gamePlayer.play();
	}

	// 代练者也是有名字的
	@Override
	public String getUserName() {
		return "代练者-李四";
	}

}

 

7.代理模式的扩展四(动态代理):

现在有个非常流行的名称叫做面向切面编程,也就是AOP(Aspect Oriented Programming),其核心就是采用了动态编程。
实现一般有两种方式,一种是基于JDK InvocationHandler接口 ,另一种是基于cglib的字节码增强技术

 

8.代理模式优点:

  • 职责清晰:真实的角色就是实际的业务逻辑,不用关心其他非本职责的事物,通过后期的代理完成一件事物
  • 高扩展性:具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,我们的代理类完全可以在不做任何修改的情况下使用
  • 代理类不仅仅是可以有自己的运算方法,通常情况下,代理的职责并不单一,它可以组合其他的真实角色,也可以实现自己的职责,比如上例中代理在play的同时,要进行收费。
分享到:
评论

相关推荐

    代理模式 Proxy Pattern

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

    C#设计模式_设计模式_C#_

    代理模式(Proxy Pattern) 行为型: 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter Pattern) 18....

    C#设计模式(23种设计模式)

    代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter ...

    设计模式代码——c#

    12. 代理模式(Proxy Pattern) 行为型 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter ...

    23种设计模式 (创建型,结构型,行为型)

    代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter ...

    Android设计模式之代理模式(Proxy Pattern)

    Android设计模式之代理模式(Proxy Pattern)

    Proxy Pattern 代理模式

    Proxy Pattern 代理模式 采用JAVA实现,可以下载看看。

    32种设计模式

    代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern) 17. 解释器...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    java 代理模式实现代码及设计详解:动态代理模式、静态代理模式

    Java24种设计模式,Java24种设计模式,24种设计模式,学会了这24种设计模式,可以打遍天下无敌手,设计模式非常重要

    2、代理模式PROXY PATTERN 3、单例模式SINGLETON PATTERN 4、多例模式MULTITION PATTERN 5、工厂方法模式FACTORY METHOD PATTERN 6、抽象工厂模式ABSTRACT FACTORY PATTERN 7、门面模式FACADE PATTERN 8、适配器...

    设计模式 之 “代理模式[Proxy Pattern]”

    NULL 博文链接:https://lym6520.iteye.com/blog/692896

    用Java实现23种设计模式

    代理模式(Proxy Pattern) 3. 行为型模式 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式...

    HE23DesignPatterns.zip

    C# 23种设计模式,包括1.单例模式 2.工厂模式3.抽象工厂模式(Abstract Factory Pattern)4....代理模式(Proxy Pattern)Pattern)7.原型模式(Prototype Pattern)8.中介者模式 9.命令模式 等设计模式

    Java设计模式

    第 2 章 代理模式【PROXY PATTERN】 ....................................................................................................... 8 第 3 章 单例模式【SINGLETON PATTERN】 .........................

    C#版 24种设计模式

    备忘录模式(Memento Pattern) 策略模式(Strategy Pattern) 抽象工厂模式(Abstract Factory Pattern) 代理模式(Proxy Pattern) 单例模式(Singleton Pattern) 迭代器模式(Iterator Pattern) 访问者模式(Visitor ...

    24种设计模式与6大设计原则

    代理模式[PROXY PATTERN] 单例模式[SINGLETON PATTERN] 多例模式[MULTITION PATTERN] 工厂方法模式[FACTORY METHOD PATTERN] 抽象工厂模式[ABSTRACT FACTORY PATTERN] 门面模式[FACADE PATTERN] 适配器模式[ADAPTER ...

    C#23种设计模式

    12. 代理模式(Proxy Pattern) 13. 模板方法(Template Method) 14. 命令模式(Command Pattern) 15. 迭代器模式(Iterator Pattern) 行为型: 16. 观察者模式(Observer Pattern) 17. 解释器模式(Interpreter ...

    book:Java案例|学习总结| .....

    cn.liguohao.design.pattern.observer : cn.liguohao.design.pattern.observer模式发布cn.liguohao.design.pattern.observer cn.liguohao.design.pattern.coffee :装饰者模式包装cn.liguohao.design.pattern.coff

    JAVA设计模式.rar

    代理模式【PROXY PATTERN】 单例模式【SINGLETON PATTERN】  多例模式【MULTITION PATTERN】  工厂方法模式【FACTORY METHOD PATTERN】 抽象工厂模式【ABSTRACT FACTORY PATTERN】 门面模式【FACADE ...

    两万字吐血总结,代理模式及手写实现动态代理(aop原理,基于jdk动态代理)

    代理模式及手实现动态代理(aop原理)一、代理模式1. 定义2. 示例(1)静态代理(2)动态代理3...代理模式(Proxy Pattern) 是一个使用频率非常高的设计模式,其定义如下: Provide a surrogate or placeholder for an

Global site tag (gtag.js) - Google Analytics