2015年6月13日土曜日

1-12. Proxy パターン

ほかのオブジェクトへのアクセスを制御するための代わりとなるものを提供します。



Proxy は RealSubject と同じ Subject インターフェースを実装し、
主に RealSubject の呼び出しを制御して負荷を軽減する処理を行います。
void client() {
	Subject subject = new Proxy();
	subject.request();
}
interface Subject {
	public void request();
}
class RealSubject implements Subject {
	public RealSubject() {
		System.out.println("RealSubject.RealSubject();");
	}
	public void request() {
		System.out.println("RealSubject.request();");
	}
}
class Proxy implements Subject {
	private Subject subjectImpl = null;
	public void request() {
		System.out.println("Proxy.request();");
		if (null == this.subjectImpl) {
			this.subjectImpl = new RealSubject();
		}
		this.subjectImpl.request();
	}
}
実行結果:
Proxy.request();
RealSubject.RealSubject();
RealSubject.request();
サンプルプログラムは、画像描画時までロードを遅延させる Proxy の例です。

実行結果:
java.png: RealImageManager_RealSubject(): 画像ロード
duke.png: ProxyImageManager_Proxy(): 画像はロードしない
MyFrame.paint()
java.png: RealImageManager_RealSubject.drawImage(): 画像描画
duke.png: ProxyImageManager_Proxy.drawImage(): 画像描画
duke.png: RealImageManager_RealSubject(): 画像ロード
duke.png: RealImageManager_RealSubject.drawImage(): 画像描画
imageUpdate: イメージ読み込み完了通知 -> paint()
MyFrame.paint()
java.png: RealImageManager_RealSubject.drawImage(): 画像描画
duke.png: ProxyImageManager_Proxy.drawImage(): 画像描画
duke.png: ProxyImageManager_Proxy.drawImage(): 画像ロード済み
duke.png: RealImageManager_RealSubject.drawImage(): 画像描画
imageUpdate: イメージ読み込み完了通知 -> paint()
MyFrame.paint()
java.png: RealImageManager_RealSubject.drawImage(): 画像描画
duke.png: ProxyImageManager_Proxy.drawImage(): 画像描画
duke.png: ProxyImageManager_Proxy.drawImage(): 画像ロード済み
duke.png: RealImageManager_RealSubject.drawImage(): 画像描画

package design_pattern;

import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;

/**
 * Proxy
 * GoF
 * ほかのオブジェクトへのアクセスを制御するための代わりとなるものを提供します。
 * 
 * @author 2015/05/26 matsushima
 */
public class ProxySample {
	/**
	 * main
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		new ProxySample().new MyFrame();
	}
	/** 画像表示用ウィンドウ。 */
	class MyFrame extends Frame {
		private static final long serialVersionUID = 1L;
		private ImageManager_Subject imageSubject1, imageSubject2;
		public MyFrame() {
			super("ProxySample");
			this.imageSubject1 = new RealImageManager_RealSubject("java.png");
			this.imageSubject2 = new ProxyImageManager_Proxy("duke.png");
			this.addWindowListener(new WindowAdapter() {
				public void windowClosing(WindowEvent e) { System.exit(0); }
			});
			this.setSize(300, 250);
			this.setVisible(true);
		}
		@Override
		public void paint(Graphics g) {
			System.out.println("MyFrame.paint()");
			super.paint(g);
			this.imageSubject1.drawImage(g, 50, 50, this);
			this.imageSubject2.drawImage(g, 150, 50, this);
		}
		@Override
		public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) {
			if (ALLBITS == infoflags) {
				System.out.println("imageUpdate: イメージ読み込み完了通知 -> paint()");
				return super.imageUpdate(img, infoflags, x, y, w, h); // paint() が呼ばれる
			}
			return true;
		}
	}
	/** 画像マネージャのインターフェース。 */
	interface ImageManager_Subject {
		public void drawImage(Graphics g, int x, int y, ImageObserver observer);
	}
	/** 画像マネージャ。 */
	class RealImageManager_RealSubject implements ImageManager_Subject {
		private Image image;
		private String path;
		public RealImageManager_RealSubject(String path) {
			System.out.println(path + ": RealImageManager_RealSubject(): 画像ロード");
			this.path = path;
			this.image = Toolkit.getDefaultToolkit().getImage(path);
		}
		public void drawImage(Graphics g, int x, int y, ImageObserver observer) {
			System.out.println(path + ": RealImageManager_RealSubject.drawImage(): 画像描画");
			g.drawImage(this.image, x, y, observer);
		}
	}
	/** 描画時に画像をロードする画像マネージャのプロキシ。 */
	class ProxyImageManager_Proxy implements ImageManager_Subject {
		private ImageManager_Subject subjectImpl = null;
		private String path;
		public ProxyImageManager_Proxy(String path) {
			System.out.println(path + ": ProxyImageManager_Proxy(): 画像はロードしない");
			this.path = path;
		}
		public void drawImage(Graphics g, int x, int y, ImageObserver observer) {
			System.out.println(path + ": ProxyImageManager_Proxy.drawImage(): 画像描画");
			if (null == this.subjectImpl) {
				this.subjectImpl = new RealImageManager_RealSubject(this.path);
			} else {
				System.out.println(path + ": ProxyImageManager_Proxy.drawImage(): 画像ロード済み");
			}
			this.subjectImpl.drawImage(g, x, y, observer);
		}
	}
}

0 件のコメント:

コメントを投稿