为其他对象提供一种代理以控制对这个对象的访问。
代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式可以提供非常好的访问控制。
代理类负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
基本上可以理解为:代理类持有实际操作对象的引用,通过公开方法将这些引用的方法提供给其它类调用。
和其它模式的区别
- 和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理迷失不能改变所代理类的接口。
- 和装饰模式的区别:装饰模式为了增强功能,而代理模式是为了加以控制。
UML
优点
- 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。
- 具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。
缺点
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
应用场景
远程代理
为一个对象在不同的地址空间提供局部代表。
虚代理
根据需要创建开销很大的对象。比如浏览网页时,图片可以使用代理先按宽高进行占位,下载好再进行显示。
保护代理
控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
智能指针
取代了简单的指针,它在访问对象时执行一些附加操作。
它的典型用途包括:
- 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它。
- 当第一次引用一个持久对象时,将它装入内存。
- 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
示例
游戏玩家(被代练对象)和游戏代练者(代理对象)的示例,其中如果游戏玩家升级则游戏代练则要进行收费。
C++
C#
1 using System; 2 3 namespace DesignPattern 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 //李雷自己打游戏 10 GamePlayer liLei = new GamePlayer("李雷"); 11 liLei.Login(); 12 liLei.KillMonster(); 13 liLei.Upgrade(); 14 15 Console.WriteLine(); 16 17 //李雷花钱请游戏代练帮其升级 18 Leveling leveling = new Leveling(liLei); 19 leveling.Login(); 20 leveling.KillMonster(); 21 leveling.Upgrade(); 22 23 Console.Read(); 24 } 25 } 26 27 /// <summary> 28 /// 游戏玩家接口. 29 /// </summary> 30 public interface IGamePlayer 31 { 32 /// <summary> 33 /// 登录. 34 /// </summary> 35 void Login(); 36 37 /// <summary> 38 /// 打怪. 39 /// </summary> 40 void KillMonster(); 41 42 /// <summary> 43 /// 升级. 44 /// </summary> 45 void Upgrade(); 46 } 47 48 /// <summary> 49 /// 玩家类. 50 /// </summary> 51 public class GamePlayer : IGamePlayer 52 { 53 private string _name; 54 55 public GamePlayer(string name) 56 { 57 _name = name; 58 } 59 60 public void Login() 61 { 62 Console.WriteLine("玩家\"" + _name + "\"登录游戏。"); 63 } 64 65 public void KillMonster() 66 { 67 Console.WriteLine("玩家\"" + _name + "\"开始打怪。"); 68 } 69 70 public void Upgrade() 71 { 72 Console.WriteLine("玩家\"" + _name + "\"等级提升一级。"); 73 } 74 } 75 76 /// <summary> 77 /// 游戏代练类. 78 /// </summary> 79 public class Leveling : IGamePlayer 80 { 81 private GamePlayer _gamePlayer; 82 83 public Leveling(GamePlayer gamePlayer) 84 { 85 _gamePlayer = gamePlayer; 86 } 87 88 public void Login() 89 { 90 _gamePlayer.Login(); 91 } 92 93 public void KillMonster() 94 { 95 _gamePlayer.KillMonster(); 96 } 97 98 public void Upgrade() 99 { 100 _gamePlayer.Upgrade(); 101 102 Console.WriteLine("游戏代练者收费。"); 103 } 104 } 105 }