【2016-10-11】【坚持学习】【Day2】【代理模式】

今天学习了代理模式。

  • 定义

官方:

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it.

我的理解:

原来是直接调用一个类的方法或者接口

现在中间多了一个代理类,先调用代理类,再通过代理类里面调用原来真实的类。

 

 

  • 结构
  • 场景

有以下几种代理模式:

1、保护代理

2、智能引用代理

    第一,第二种代理例子:

        原有系统:直接调用查询服务接口

        新需求:要验证用户是否登录成功(新)=》调用原有查询接口=》记录查询日志(新)

 

class Proxy : Subject
{
private RealSubject realSubject = new RealSubject(); //维持一个对真实主题对象的引用
public void PreRequest() 
{
…...
}
public override void Request() 
{
PreRequest();
    realSubject.Request(); //调用真实主题对象的方法
    PostRequest();
}
public void PostRequest() 
{
……
}
}
View Code

 

 

3、远程代理(通过调用远程服务器实现业务)

4、缓冲代理(查询很大的数据时候,可以保存在缓存中,下次调用就直接去缓存)

 

public static class ProductDataProxy
{
private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings ["ProductCacheDuration"]);
private static readonly bool enableCaching = bool.Parse(ConfigurationManager. AppSettings["EnableCaching"]); 
public static IList GetProductsByCategory(string category)
{        
Product product = new Product();
//如果缓存被禁用,则直接通过product对象来获取数据
if (!enableCaching)
{
return product.GetProductsByCategory(category);
}
string key = "product_by_category_" + category;
//从缓存中获取数据
IList data = (IList )HttpRuntime.Cache[key];  
//如果缓存中没有数据则执行如下代码
if (data == null)
{            
data = product.GetProductsByCategory(category);            
//通过工厂创建AggregateCacheDependency对象
AggregateCacheDependency cd = DependencyFacade.GetProductDependency (); 
//将数据存储在缓存中,并添加必要的AggregateCacheDependency对象
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(product Timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null); 
}
return data;
}
……
}
View Code

 

 

5、虚拟代理

书上解析:

对于一些占用系统资源较多或者加载时间较长的对象,可以给这些对象提供一个虚拟代理
在真实对象创建成功之前虚拟代理扮演真实对象的替身,而当真实对象创建之后,虚拟代理将用户的请求转发给真实对象
使用一个“虚假”的代理对象来代表真实对象,通过代理对象来间接引用真实对象,可以在一定程度上提高系统的性能

 例子:

CD封面:加载要好慢,那么先弄一个简单的出来,然后异步加载真实数据,并且呈现。

//实现Icon接口  
public class ImageProxy implements Icon {  
    ImageIcon imageIcon;  
    URL imageURL;  
    Thread retrievalThread;  
    boolean retrieving = false;  
  
    // 将图片的URL传入构造器中  
    public ImageProxy(URL url) {  
        imageURL = url;  
    }  
  
    // 在图像加载完毕前,返回默认的宽和高  
    // 图像加载完毕后,装给iamgeIcon处理  
    public int getIconWidth() {  
        if (imageIcon != null) {  
            return imageIcon.getIconWidth();  
        } else {  
            return 800;  
        }  
    }  
      
    public int getIconHeight() {  
        if (imageIcon != null) {  
            return imageIcon.getIconHeight();  
        } else {  
            return 600;  
        }  
    }  
  
    // 当要在屏幕上绘制图像时,就调用此方法  
    public void paintIcon(final Component c, Graphics g, int x, int y) {  
        // 如果已经有了icon,就画出  
        if (imageIcon != null) {  
            imageIcon.paintIcon(c, g, x, y);  
        } else {  
            // 还没有icon时,就显示“加载中...”的消息  
            g.drawString("CD封面加载中,请稍后...", x + 300, y + 190);  
            if (!retrieving) {  
                retrieving = true;  
                  
                // 在这个线程中加载真正的icon图像。注意,加载图像和ImageIcon是同步(synchronous)  
                // 也就是说,只有在加载完之后,ImageIcon构造器才会返回。这样,我们的程序会耗在这里  
                // 所以要把加载变成异步(asynchronous)的。  
                retrievalThread = new Thread(new Runnable() {  
                    public void run() {  
                        try {  
                            imageIcon = new ImageIcon(imageURL, "CD Cover");  
                            c.repaint();  
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                    }  
                });  
                retrievalThread.start();  
            }  
        }  
    }  
  
}
View Code

 

 

 

posted @ 2016-10-12 14:52  zscmj  阅读(149)  评论(0编辑  收藏  举报