Proxy パターン (あるオブジェクトへのアクセスを制御するため, 共通のインタフェースを持つオブジェクトが代理をする)

[Proxy] という英単語は, [代理人] を意味する.

このパターンは, 本人の代理人となるオブジェクトが本人でなくともできる処理を受け待ち, [どうしても本人でないと...] という場合のみ, 本人に処理を任せるというパターン.

このパターンは, [Decorator] パターンと酷似しているが, それぞれ目的が異なっている. [Decorator] パターンの目的は, 新しい機能を追加するための工夫であり, [Proxy] パターンの目的は, あるオブジェクトへの負荷を軽減 (そのために代理して処理を実施) するための工夫となる.

役割

  1. Subject (主体, 本人):
[Proxy] と [RealSubject] の共通のインタフェースを定義する. 上記により, 双方 のクラスを同一視でき, 同じメソッドで [Proxy] が肩代わりできる.
  1. Proxy (代理人):
[Subject] のインタフェースを実装する. [Client] からの要求を可能な限り処理 するが, どうしても自分で処理できない場合は, [RealSubject] に処理を委任する. [Proxy] は, どうしても [RealSubject] が必要になった時点で, [RealSubject] オブジェクトを生成し, 処理を委任する.
  1. RealSubject (真の主体, 本人):
[subject] のインタフェースを実装する. [Proxy] では, どうしても処理できない 場合に, [Proxy] から処理を委任される.
  1. Client (利用者):
[Proxy] パターンを適用したクラス利用し処理する.

クラス図

Proxy パターンのクラス図

_images/designpattern-proxy011.gif

ソースコード

  1. Subject.java
1
2
3
4
5
6
public abstract class Subject{
    protected String name;
    public abstract void request1(String name);
    public abstract void request2();
    public abstract void request3();
}
  1. Proxy.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Proxy extends Subject{
    RealSubject realSubject;

    public void request1(String name){
	System.out.println("代理: Proxy-r1()");
	super.name = name;
    }

    public void request2(){
	if(realSubject == null){
	    System.out.println("代理: Proxy-r2()");
	}else{
	    realSubject.request2();
	}
    }

    public void request3(){
	System.out.println("代理: Proxy-r3()");
	if(realSubject == null){
	    realSubject = new RealSubject();
	    realSubject.request1(name);
	}

	realSubject.request3();
    }
}
  1. RealSubject.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class RealSubject extends Subject{
    public void request1(String name){
	System.out.println("本人: RealSubject-r1()");
	super.name = name;
    }

    public void request2(){
	System.out.println("本人: RealSubject-r2()");
    }

    public void request3(){
	System.out.println("本人: RealSubject["+name+"]-r3()");
    }
}
  1. Client.java
1
2
3
4
5
6
7
8
9
public class Client{
    public static void main(String[] args){
	Subject sub = new Proxy();

	sub.request1("wtopia");
	sub.request2();
	sub.request3();
    }
}

上記のプログラムの実行結果:

[wtopia Proxy]$ java Client
代理: Proxy-r1()
代理: Proxy-r2()
代理: Proxy-r3()
本人: RealSubject-r1()
本人: RealSubject[wtopia]-r3()