ファサード

概要

ClientがMarimoとSpinach(ほうれん草)のカロリーの最大値を求めるプログラムを書く。
MarimoとSpinachを複数保持できるCollectionを容易して、Clientがどうにかしてカロリーの最大値を求める。

利用なし

以下利用なしコード

Marimo.java

public class Marimo {
	private int cal = 0;
	public Marimo(){
		this.cal = (int)(Math.random() * 100);
	}
	public int getCal(){
		return this.cal;
	}
}

MarimoCollection.java

import java.util.AbstractList;
import java.util.ArrayList;


public class MarimoCollection extends AbstractList<Marimo>{
	private ArrayList<Marimo> list;
	public MarimoCollection(){
		list = new ArrayList<Marimo>();
	}
	
	@Override
	public boolean add(Marimo m){
		return list.add(m);
	}
	
	@Override
	public Marimo get(int index) {
		
		return list.get(index);
	}

	@Override
	public int size() {
		
		return list.size();
	}
	
}

Spinach.java

public class Spinach {
	private int cal = 0;
	public Spinach(){
		this.cal = (int)(Math.random()*100);
	}
	public int getCal(){
		return this.cal;
	}
}

SpinachCollection.java

import java.util.AbstractList;
import java.util.ArrayList;


public class SpinachCollection extends AbstractList<Spinach>{
	private ArrayList<Spinach> list;
	
	public SpinachCollection(){
		list = new ArrayList<Spinach>();
	}
	
	@Override
	public boolean add(Spinach s){
		return list.add(s);
	}
	
	@Override
	public Spinach get(int index) {
		return list.get(index);
	}

	@Override
	public int size() {
		return list.size();
	}

}

Client.java

public class Client {
	MarimoCollection mc;
	SpinachCollection sc;
	public Client(){
		mc = new MarimoCollection();
		sc = new SpinachCollection();
		
		this.makeWorld();
	}
	public void makeWorld(){
		for(int i = 0; i < 5; i++){
			mc.add(new Marimo());
		}
		for(int i = 0; i < 5; i++){
			sc.add(new Spinach());
		}
	}
	
	public int getMaxCal(){
		int max = 0;
		for(int i = 0; i < mc.size(); i++){
			max = Math.max(mc.get(i).getCal(),max);
		}
		for(int i = 0; i < sc.size(); i++){
			max = Math.max(sc.get(i).getCal(),max);
		}		
		return max;
	}
	
	public static void main(String[] args){
		Client c = new Client();
		int mCal = c.getMaxCal();
		System.out.println("Max Calory: " + mCal);
	}
}

何が問題か?

このコードはClientがMarimoとSpinach、とそれらのCollectionの構造を知っていることが前提になっている。
このままでは、MarimoやSpinachに変更を加えたとき、その変更がClientにも波及してしまう。

利用する

カロリーの最大値を求めるという処理を切り離して別クラスCaloryMaterにする。
こうすることで、MarimoやSpinachへの依存はこのCaloryMaterでストップする。
ClientはCaloryMaterの使い方を知っているだけでOK。

CaloryMater.java

public class CaloryMater {
	MarimoCollection mc;
	SpinachCollection sc;
	
	public CaloryMater(){
		mc = new MarimoCollection();
		sc = new SpinachCollection();
		
		this.makeWorld();
	}
	
	public void makeWorld(){
		for(int i = 0; i < 5; i++){
			mc.add(new Marimo());
		}
		for(int i = 0; i < 5; i++){
			sc.add(new Spinach());
		}
	}
	
	public int getMaxCal(){
		int max = 0;
		for(int i = 0; i < mc.size(); i++){
			max = Math.max(mc.get(i).getCal(),max);
		}
		for(int i = 0; i < sc.size(); i++){
			max = Math.max(sc.get(i).getCal(),max);
		}		
		return max;
	}
}

Client.java

public class Client {
	private CaloryMater cm;
	public Client(){
		this.cm = new CaloryMater();
	}
	public int getMaxCal(){
		return this.cm.getMaxCal();
	}
	
	public static void main(String[] args){
		Client c = new Client();
		int mCal = c.getMaxCal();
		System.out.println("Max Calory: " + mCal);
	}
}

利点とか欠点とか

  • 利点
    • クライアントコードから余計な依存関係を取り除くことができる
  • 欠点
    • Facadeに無い機能をClientから呼び出すことは出来ない

当たり前の事を書いてしまった。まぁどんなパターンも依存関係を取り除く代わりにインターフェースを切るので当然といえば当然か。