一、代理模式概述
Proxy代理模式,它指的是不需要本人亲自完成工作,而是寻找代理人帮助完成,但是代理人能代替本人做的事情是有限的,有一些问题自己无法解决还是必须要找到被代理人解决问题;
为什么需要代理,举个生活的例子,打官司一般都会有代理律师,虽然我们也可以学习法律,但是成本很高,而有了律师以后,我们就不必再关心各种流程细节,但是当律师需要求证信息的时候,仍然需要被代理人配合;
比如,我们在游戏中经常会封装一些Manager,它其实也是一种代理的概念;
二、程序示例
如下是模拟一个带名字的打字机,就是将文字显示到界面上;
为了让代理类和被代理类具有行为的一致性,我们需要定义一个Printable接口,然后两个类都要实现这个接口;
public interface Printable {
public abstract void SetPrinterName(String name);
public abstract String GetPrinterName();
public abstract void Print(String str);
}
程序的前提是生成Printer实例是很耗的,因此我们会尽可能延迟到真正使用时才会创建;
Printer类是真正做打印工作的类;
public class Printer : Printable{
private String name;
public Printer() {
HeavyJob("正在生成Printer实例");
}
public Printer(String name) {
this.name = name;
HeavyJob("正在生成Printer实例" + name);
}
public void SetPrinterName(String name) {
this.name = name;
}
public String GetPrinterName() {
return this.name;
}
public void Print(String str) {
System.Console.WriteLine(str);
}
private void HeavyJob(String msg) {
System.Console.WriteLine(msg);
for (int i = 0; i < 5; i++) {
try
{
Thread.Sleep(1000);
}
catch (ThreadInterruptedException e) { }
System.Console.Write(".");
}
System.Console.WriteLine("End");
}
}
而PrinterProxy只是代理,因此在需要打印的时候,它还是需要找到它代理的打印实例,然后调用实例的打印方法来完成工作;
public class PrinterProxy : Printable{
private String name;
private Printer real;
public PrinterProxy(String name) {
this.name = name;
}
public void SetPrinterName(String name) {
if (real != null) {
real.SetPrinterName(name);
}
this.name = name;
}
public String GetPrinterName() {
return name;
}
public void Print(String str) {
Realize();
real.Print(str);
}
private void Realize() {
if (real == null) {
real = new Printer(name);
}
}
}
client测试代码
Printable p = new PrinterProxy("Alice");
System.Console.WriteLine("my name is : " + p.GetPrinterName());
p.SetPrinterName("Bob");
System.Console.WriteLine("my name is : " + p.GetPrinterName());
p.Print("hello world");
三、分析总结
在Proxy中,一般有以下几个角色
Subject,主体,对应上面的Printable,使得代理和被代理之间有统一的接口,由于Subject存在,Client就不必在意它用的究竟是Proxy还是RealSubject;
Proxy,代理人,Proxy会尽量处理来自Client的请求,只有当自己不能处理时,它才会将工作交给RealSubject角色;
RealSubject,只有当Proxy无法胜任工作时才出场;
类图关系如下: