只在必要时生成实例-Proxy模式

888 阅读2分钟

1、引入

代理模式,顾名思义是委托代理人来进行某些工作的模式。

在现实生活中,一般在委托人过忙时,会寻找代理人帮忙处理,而代理人虽然可以处理部分事务,但任然存在着不能解决的问题,这时候又要交回委托人处理。在代理模式中也是如此。

代理模式由以下几部分组成:

  • 被代理者
  • 代理者
  • 使用者

2、示例

实现以下功能:被代理者为一台启动慢的打印机,使用者有时只需要获取或设置打印机名字,有时需要用打印机打印东西。

2.1、被代理者打印机

首先有接口:

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

打印机实现类:

public class Printer implements Printable{
    private String name;

    public Printer(String name) {
        this.name=name;
        heavyJob("Printer实例生成中");
    }

    @Override
    public void setPrinterName(String name) {
        this.name=name;
    }

    @Override
    public String getPrinterName() {
        return name;
    }

    @Override
    public void print(String str) {
        System.out.println("========="+name+"=======");
        System.out.println(str);
    }

    private void heavyJob(String msg) {
        System.out.println(msg);
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(".");
        }
        System.out.println("end");
    }
}

2.2、代理类

实现代理类,可以替打印机完成名字获取与设置功能

public class PrinterProxy implements Printable{
    private String name;
    private Printer real;

    public PrinterProxy() {
    }

    public PrinterProxy(String name) {
        this.name = name;
    }

    @Override
    public void setPrinterName(String name) {
        if (real != null) {
            real.setPrinterName(name);
        }
        this.name=name;
    }

    @Override
    public String getPrinterName() {
        return name;
    }

    @Override
    public void print(String str) {
        realize();
        real.print(str);
    }

    private synchronized void realize() {
        if (real == null) {
            real=new Printer(name);
        }
    }
}

2.3、测试

当获取和设置名字时,只需要创建代理对象即可;当真正需要打印时,代理对象内才会创建打印机实例。

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

运行结果:

image.png

3、tips

  • 代理模式将被代理者和代理者的职责区分开了,各司其职,实现了解耦的功效,并且部分条件下能减少内存占用和运行速度。
  • 代理模式相当于在被代理者和使用者之间加了一层,多出来的这一层可以起到保护内层、方便拓展等功能。
  • 被代理类和代理类实现了相同的接口,因此在外界使用者看了他俩是一样的。