概要
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から呼び出すことは出来ない
当たり前の事を書いてしまった。まぁどんなパターンも依存関係を取り除く代わりにインターフェースを切るので当然といえば当然か。