デザインパターンstrategyについて勉強した

strategyパターンとは

戦略などのような意味です。
プログラミングで言えば「アルゴリズム」もstrategyと捉えることもできます。

ある問題を解くときに、方法Aと方法Bがあったとします。
AとBどちらを使えば効率がいいか試してみるとき、両方作って別のクラスとして管理するのではないかと思います。
Aのコードを試した後にコードを全て消してBを書き直すなんてことはしませんね。

このような、AとBを両方作っていつでも切り替えができるようにするデザインパターンをstrategyパターンと呼びます。

コード例

ランダムな数列を昇順に並べ替えるプログラムを例にします。

Sorterインタフェース

public interface Sorter {

	int[] sort(int[] list) ;
}

後述する全てのソート方法は、このインタフェースを実装させます。

sortメソッドは引数に渡された数列をソートして返すように宣言しています。
サブクラスが実装します。

実装

BublleSortクラス

public class BublleSort implements Sorter {

	@Override
	public int[] sort(int[] list) {
		int[] newlist = list.clone();
		int s ;

		for(int i=1;i<newlist.length;i++) {
			for(int j=i;j<newlist.length;j++) {
				if(newlist[j-1]>newlist[j]) {
					s = newlist[j-1];
					newlist[j-1] = newlist[j];
					newlist[j] = s;
				}
			}
		}

		return newlist;
	}
}

ソート方法の一つである、バブルソートを実装したクラスです。

※ソートの知識が浅いため、ここではこのバブルソートだけを実装例とします。

StrategySorterクラス

public class StrategySorter {

	public StrategySorter(Sorter sorter) {

		int[] list = new int[99999];
		Random random = new Random();

		for(int i=0;i<list.length;i++) {
			list[i] = random.nextInt();
		}

		System.out.println("start");
		long time = System.currentTimeMillis();
		sorter.sort(list);
		System.out.println(System.currentTimeMillis()-time);
	}
}

コンストラクタの引数から渡されるSorterを使って数列をソートします。
Sorterはインタフェースであり、実際に渡されてくるクラスが何であるのかはわかりません。
このクラスは実際に使われているのがどんなアルゴリズムであるのかを意識しなくても良いように書かれています。

list変数はランダムな数列が入れられます。
random変数はランダム数列生成期です。

次のforループではランダム数列を作っています。

コンソールに"start"を表示し、現在の時間をミリ秒で記憶します。
sorter引数からsortメソッドを呼び出し、ソートを開始します。
ソートが終了すると、この時点の時間をミリ秒で確認し、先ほど記憶したスタート時間を引き算します。
この計算された時間がソートにかかった時間となります。

実行

public class Main {

	public static void main(String[] args) {
		new StrategySorter(new BublleSort());
	}
}

実行します。
mainメソッドではコンストラクタの引数にBublleSortクラスのインスタンスを渡しています。
これで先ほど作ったバブルソートアルゴリズムを選択したことになります。

特徴

状態を切り替えるstateパターンにも似ていますが、あちらは状態の切り替えを前提とするパターン(頻繁に切り替えている)のに対して、strategyパターンは試しに検証してみるような場面で使われたりします。

まとめ

今回私がソートアルゴリズムに疎いため、なんとなく知っているバブルソートだけの実装としました。
Sorterインタフェースを実装した別のクラス(QuickSortクラスやMergeSortクラスなど)を作って切り替えることで、strategyパターンは完成できます。