前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之代理模式(Proxy模式)代理模式的引入代理模式的实例程序代理模式分析

设计模式之代理模式(Proxy模式)代理模式的引入代理模式的实例程序代理模式分析

作者头像
desperate633
发布2018-08-22 16:09:58
3670
发布2018-08-22 16:09:58
举报
文章被收录于专栏:desperate633desperate633

  • 代理模式的引入
  • 代理模式的实例程序
  • 代理模式的分析

代理模式的引入

Proxy是代理人的意思,指的是代替别人进行工作的人。当不一定需要本人亲自去做的工作的时候,就可以寻找代理人去完成。

但在代理模式中,往往是相反的,通常是代理人碰到工作,就交给被代理的对象去完成,代理人只完成一些准备工作或者收尾工作。

如果读者了解过spring框架的话,就会知道aop也就是面向切面编程其实运用的就是动态代理模式,这可以让被代理的对象专注于完成自己的本职工作,而代理对象可以进行工作前的日志记录,时间计算,在工作之后进行日志记录,收尾工作等附加的功能,需要正式做工作的时候就交给被代理去做。就像插了两个刀到这个被代理的对象前后。所以形象的叫做面向切面编程。

关于动态代理模式和静态代理模式,感兴趣的读者可以参考笔者的另一篇博文:

Java动态代理与静态代理http://www.jianshu.com/p/b5e340ec9551

代理模式的实例程序

我们会实现一个打印机,向屏幕打印一串字符串,然后交给代理对象去完成这个功能。

首先看一下类图:

image.png

Printer类:

代码语言:javascript
复制
package Proxy;

public class Printer implements 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 name;
    }
    public void print(String string) {              // 显示带打印机名字的文字
        System.out.println("=== " + name + " ===");
        System.out.println(string);
    }
    private void heavyJob(String msg) {             // 重活
        System.out.print(msg);
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.print(".");
        }
        System.out.println("结束。");
    }
}

Printable接口:

代码语言:javascript
复制
package Proxy;

public interface Printable {
    public abstract void setPrinterName(String name);
    
    public abstract String getPrinterName();
    
    public abstract void print(String string); 
}

PrinterProxy类,利用反射机制,动态生成被代理的对象,并且延迟初始化到需要调用它的时候再初始化

代码语言:javascript
复制
package Proxy;

public class PrinterProxy implements Printable {
    private String name;            // 名字
    private Printable real;         // “本人”                 
    private String className;       // “本人”的类名       
    public PrinterProxy(String name, String className) {      // 构造函数     
        this.name = name;
        this.className = className;                                                 
    }
    public synchronized void setPrinterName(String name) {  // 设置名字
        if (real != null) {
            real.setPrinterName(name);  // 同时设置“本人”的名字
        }
        this.name = name;
    }
    public String getPrinterName() {    // 获取名字
        return name;
    }
    public void print(String string) {  // 显示
        realize();
        real.print(string);
    }
    private synchronized void realize() {   // 生成“本人”
        if (real == null) {
            try {                                                                       
                real = (Printable)Class.forName(className).newInstance();               
                real.setPrinterName(name);                                              
            } catch (ClassNotFoundException e) {                                        
                System.err.println("没有找到 " + className + " 类。");      
            } catch (Exception e) {                                                     
                e.printStackTrace();                                                    
            }                                                                           
        }
    }
}

Main类测试:

代码语言:javascript
复制
package Proxy;

public class Main {
    public static void main(String[] args) {
        Printable p = new PrinterProxy("Alice", "Proxy.Printer");                 
        System.out.println("现在的名字是" + p.getPrinterName() + "。");
        p.setPrinterName("Bob");
        System.out.println("现在的名字是" + p.getPrinterName() + "。");
        p.print("Hello, world.");
    }
}

运行结果:

image.png

代理模式分析

代理模式中的角色:

  • Subject(主体) Subject角色定义了使proxy和realsubject角色之间具有一致性的接口。这个接口提供了一个使用的好处,就是client不必却分它使用的是代理对象还是真实对象。 对应实例中Printable角色
  • Proxy(代理人) Proxy角色会尽量处理来自Client角色的请求。只有当自己不能处理的时候,就交给工作交给真实对象。代理对象只有在有必要时才会生成真实的对象。 实例中对应的是PrinterProxy对象。
  • RealSubject(真实对象) 就是实际完成工作的对象,对应实例中的Printer对象。

代理模式的类图:

image.png

  • 用代理人来提升速度 关键就在于延迟初始化。 我们可以等到需要使用到真实对象的功能才初始化。这样的好处就是可以提升性能。从我们的实例中可能看不出这个优势,假设我们有一个大型系统,如果我们都在系统启动的时候,把所有功能初始化,所有实例初始化,那么显然系统的启动将会变得很慢。但如果我们采用代理模式,那么就会在必须的时候,在初始化对象。这样就加快了系统的启动速度。
  • 代理和委托 其实我们学习了那么多设计模式,是不是感觉委托简直无处不在。几乎每个设计模式都会用到委托,代理模式也不意外,就是代理了对象委托了真实对象。 因为委托可以是对象之间发生联系,互相调用。所以委托在很多设计模式中都存在。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.07.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代理模式的引入
  • 代理模式的实例程序
  • 代理模式分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档