我也设计模式——11.Proxy

这个模式用途很多,先看它的UML:

    abstract public class Subject
    
{
        
abstract public void Request();
    }


    
public class RealSubject : Subject
    
{
        
public override void Request()
        
{
            
//Do Something
        }

    }


    
public class Proxy : Subject
    
{
        
private RealSubject realSubject;

        
public override void Request()
        
{
            
//关键是这句话
            realSubject.Request();
        }

    }

 Client端使用如下:
            Subject subject = new Proxy();
            subject.Request();

Proxy有以下用途:
1.远程代理     Remoting和WebService都是基于此技术,这里就不多说了。
2.虚代理        单元测试中的Mock技术,以及加载大图片/处理大对象时的等待过程
    Mock技术:如果现在的RealSubject类的Request()方法还没写好,可以继承Subject基类生成Proxy,这是Proxy类的Request()方法这么写:

        public override void Request()
        
{
            
//从配置文件中读取是否出于测试状态
            bool isTest = GetConfiguration("isText");

            
if (isTest)
            
{
                
//写一些期望的假操作
            }

            
else
            
{
                realSubject.Request();
            }

        }

    加载大图片:

    public interface Imager
    
{
        Image getImage();
    }


    
public class LargeImage : Imager
    
{
        
public Image getImage()
        
{
            
return new Bitmap(@"BigImage.jpg"); ;
        }

    }


    
public class ProxyImage : Imager
    
{
        
private Timer tm;
        
private bool isReady;
        
private LargeImage largeImage;
        
        
public ProxyImage()
        
{
            isReady 
= false;

            tm 
= new Timer(
                
delegate
                
{
                    isReady 
= true;
                    tm.Dispose();
                }
,
                
this100000);
        }

        
        
public Image getImage()
        
{
            
if (isReady)
            
{                
                
return largeImage.getImage();
            }

            
else
            
{
                
return new Bitmap("SmallImage.gif");
            }

        }

    }

在Client端调用方法:

        private ProxyImage imgProxy;

        
private void Form1_Load(object sender, EventArgs e)
        
{
            imgProxy 
= new ProxyImage();
        }


        
private void btnLoad_Click(object sender, EventArgs e)
        
{
            
//Pic为一个PictureBox控件
            Pic.Image = imgProxy.getImage();
        }

注意这句话:            
        tm = new Timer(
                delegate
                {
                    isReady = true;
                    tm.Dispose();
                },
                this, 10000, 0);
关键就是这句话,开始isReady为false,加载小图片。10秒钟后才将isReady设置为true,并使Timer失效,从而再次调用ProxyImage的getImage()方法,加载大图片。

3.保护代理     控制对原始对象的访问,如增加/去除权限

原有系统的方法GetDisCount(),只有Role=管理员时才可以调用。

    public class CompDiscount
    
{
        
private string role;

        
public string Role
        
{
            
get return role; }
            
set { role = value; }
        }


        
public Double GetDiscount()
        
{
            
if (role == "admin")
            
{
                
return 1000;
            }

            
else
            
{
                
throw new Exception();
            }

        }

    }

现在要直接使用这个方法,而跳过权限控制,可以从中派生出一个子类ProxyCompDiscount:



    public class ProxyCompDiscount : CompDiscount
    
{
        
private CompDiscount c;

        
public ProxyCompDiscount()
        
{
            c 
= new CompDiscount();
            c.Role 
= "admin";
        }


        
public new Double GetDiscount()
        
{
            
return c.GetDiscount();
        }

    }

以上是去除多余的权限,相当于短路操作。反之,也可以使用同样的方法,增加权限。

4.智能指引     在访问对象时执行一些附加的操作,如强制类型集

    public class Field 
    
{
        
private string fieldName;

        
public Field(string fieldName)
        
{
            
this.fieldName = fieldName;
        }

    }


    
public class FieldCollection : CollectionBase
    
{
        
public int Add(Field field)
        
{
            
return InnerList.Add(field);
        }


        
public Field Add(string fieldName)
        
{
            Field field 
= new Field(fieldName);
            Add(field);

            
return field;
        }


        
public void Add(params string[] fields)
        
{
            
foreach (string field in fields)
            
{
                Add(field);
            }

        }


        
public Field this[int index]
        
{
            
get 
            
{
                
return (Field)InnerList[index];
            }

        }


        
public void Remove(Field field)
        
{
            InnerList.Remove(field);
        }

    }

在Client端,Proxy模式不用知道被代理的对象;而Decorator模式需要知道被修饰的对象。这是二者的区别。

posted @ 2007-10-03 16:44  包建强  Views(820)  Comments(0Edit  收藏  举报