java ----代理模式

我们先来分析代理这个词。

一、代理

代理是英文 Proxy 翻译过来的。我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了。

她们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人。

这里写图片描述

按理说,顾客可以直接从厂家购买产品,但是现实生活中,很少有这样的销售模式。一般都是厂家委托给代理商进行销售,顾客跟代理商打交道,而不直接与产品实际生产者进行关联。

所以,代理就有一种中间人的味道。

接下来,我们说说软件中的代理模式。

二、代理模式

代理模式是面向对象编程中比较常见的设计模式。
这里写图片描述

这是常见代理模式常见的 UML 示意图。

需要注意的有下面几点:

  1. 用户只关心接口功能,而不在乎谁提供了功能。上图中接口是 Subject。
  2. 接口真正实现者是上图的 RealSubject,但是它不与用户直接接触,而是通过代理。
  3. 代理就是上图中的 Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
  4. 用户调用 Proxy 的时候,Proxy 内部调用了 RealSubje

三、代理模式的实例程序

我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage 对象加载的内存占用。

ProxyPatternDemo,我们的演示类使用 ProxyImage 来获取要加载的 Image 对象,并按照需求进行显示。

代理模式的 UML 图

步骤 1

创建一个接口。

Image.java

public interface Image {
   void display();
}

步骤 2

创建实现接口的实体类。

RealImage.java

public class RealImage implements Image {
 
   private String fileName;
 
   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }
 
   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }
 
   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}

ProxyImage.java

public class ProxyImage implements Image{
 
   private RealImage realImage;
   private String fileName;
 
   public ProxyImage(String fileName){
      this.fileName = fileName;
   }
 
   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

步骤 3

当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。

ProxyPatternDemo.java

public class ProxyPatternDemo {
   
   public static void main(String[] args) {
      Image proxyImage = new ProxyImage("test_10mb.jpg");
 
      // 图像将从磁盘加载
      proxyImage.display(); 
      System.out.println("");
      // 图像不需要从磁盘加载
      proxyImage.display();  
   }
}

步骤 4

执行程序,输出结果:

Loading test_10mb.jpg
Displaying test_10mb.jpg

Displaying test_10mb.jpg

四、代理模式分析

代理模式中的角色:

  • Subject(主体)
    Subject角色定义了使proxy和realsubject角色之间具有一致性的接口。这个接口提供了一个使用的好处,就是client不必却分它使用的是代理对象还是真实对象。
    对应实例中Printable角色

  • Proxy(代理人)
    Proxy角色会尽量处理来自Client角色的请求。只有当自己不能处理的时候,就交给工作交给真实对象。代理对象只有在有必要时才会生成真实的对象。
    实例中对应的是PrinterProxy对象。

  • RealSubject(真实对象)
    就是实际完成工作的对象,对应实例中的Printer对象。

代理模式的类图:

img

  • 用代理人来提升速度
    关键就在于延迟初始化。
    我们可以等到需要使用到真实对象的功能才初始化。这样的好处就是可以提升性能。从我们的实例中可能看不出这个优势,假设我们有一个大型系统,如果我们都在系统启动的时候,把所有功能初始化,所有实例初始化,那么显然系统的启动将会变得很慢。但如果我们采用代理模式,那么就会在必须的时候,在初始化对象。这样就加快了系统的启动速度。
  • 代理和委托
    其实我们学习了那么多设计模式,是不是感觉委托简直无处不在。几乎每个设计模式都会用到委托,代理模式也不意外,就是代理了对象委托了真实对象。
    因为委托可以是对象之间发生联系,互相调用。所以委托在很多设计模式中都存在。


参考文章 :
  • https://www.jianshu.com/p/5ab7672b935f
  • https://blog.csdn.net/briblue/article/details/73928350
  • https://www.runoob.com/design-pattern/proxy-pattern.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章