デザインパターン Proxy:必要になってから作る

概要

Proxy:代理人
本来の処理オブジェクトとは別の代理人オブジェクトに処理を代理させる手法
負荷の高い処理に使用する。

クラス図


本例

-:private

サービス側

Subject(主体)

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

Proxy(代理人)

public class PrintProxy implements Printable {

 private String name;
 private Printer real;

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

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

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

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

 private void realize() {
  if (this.real == null) {
   ここで初めて本来の処理オブジェクトに処理を渡す
   this.real = new Printer(this.name);
  }
 }
}

RealSubject(実際の主体)

public class Printer implements Printable {
 private String name;

 public Printer() {
  heavyJob("Printerのインスタンス作成中");
 }

 public Printer(String name) {
  this.name = name;
  heavyJob(String.format("Printerのインスタンス(%s)作成中", this.name));
 }

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

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

 @Override
 public void print(String string) {
  System.out.println(String.format("===%s===", this.name));
  System.out.println(string);
 }

 private void heavyJob(String string) {
  System.out.println(string);
  for (int i = 0; i < 5; i++) {
   try {
    Thread.sleep(1000);
   }catch(InterruptedException e) {
    // 何もしない
   }
   System.out.println(".");
  }
  System.out.println("完了");
 }
}

利用者側

public class Main {
 public static void main(String[] args) {
  Printable p = new PrintProxy("Java");
  System.out.println(String.format("名前は現在%sです。", p.getPrinterName()));
  p.setPrinterName("PHP");
  System.out.println(String.format("名前は現在%sです。", p.getPrinterName()));
  ここで初めてPrinterインスタンスが作成される
  p.print("Hello World.");
  
  p.setPrinterName("PHP");
  p.print("Hello World.");
 }
}


結果
名前は現在Javaです。
名前は現在Javaです。
Printerのインスタンス(Java)作成中
.
.
.
.
.
完了
===Java===
Hello World.
===PHP===
Hello World.