そらとぶへび

仕事・プライベートを通しての気づき、JavaやPHP、データベースやサーバの話などこつこつと書いていきます

インタフェースの設計

インタフェースとは、振る舞いを部品として抽象化するための言語仕様。クラスと違い実体化できずメソッドも実装を持たない。インタフェースの設計にあたっては、クラス間の依存を少なくするよう留意する。
以下に留意点をまとめる。

コードの依存性

他のクラスへの依存性が少ないほど、そのコードは堅牢ということになる。通常、クラスへの依存より、インタフェースへの依存のほうが保守に強いコードとなる。

・変化しにくい振る舞いを規定してインタフェースにまとめる。
・クラスはインタフェースを継承することで、変化しにくい部分を表明する。
・可能な限りクラスよりインタフェースに依存するように書く。


インタフェースと抽象クラス

実装上、インタフェースの役割は抽象クラスでも担える。ただし根本的な目的は異なっている。抽象クラスによる実装を伴う継承関係はクラス間に強い依存関係をもたらしてしまう。そのため、インタフェースは実装を一切持たず、振る舞いのみを規定する機能に限定されている。

インタフェース :振る舞いを規定する。
抽象クラス   :実装の拡張を行う。

インタフェース実装例

インタフェース依存によりクラス間の依存を減らすことができる。直接、メソッドを呼び出せばコードとしては単純になるが、クラス間の依存が強くなる。

MyFilter.java (インタフェース)

public interface MyFilter {
	String doJob(String input);
}

ReplaceFilter.java (インタフェースの実装クラス)

public class ReplaceFilter implements MyFilter {

	private final String oldStr;
	private final String newStr;

	
	public ReplaceFilter(String oldStr,String newStr){
		this.oldStr = oldStr;
		this.newStr = newStr;
	}
	@Override
	public String doJob(String input) {
		return input.replaceAll(oldStr, newStr);
	}
}

CapitalizeFilter.java (さらにインタフェースを実装したクラス)

public class CapitalizeFilter implements MyFilter {
	@Override
	public String doJob(String input) {
		return input.toUpperCase();
	}
}

MyEcho.java (実行クラス)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class MyEcho {
	
	private final List<MyFilter> filters;

	public MyEcho(List<MyFilter> filters){
		this.filters = filters;
	}
	
	
	public void exec() {
		try(BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) {
			while(true) {
				System.out.println("Input any text");
				String msg = stdin.readLine();
				
				String output = msg;
				for(MyFilter filter : filters) {
					output = filter.doJob(output);
				}
				
				System.out.println("You sey " + output);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String... args) throws ReflectiveOperationException{
		MyEcho echo = new MyEcho(Arrays.asList(new ReplaceFilter("he", "she"),new CapitalizeFilter()));
		echo.exec();
	}

}

テキストの整形処理部分を外部に追い出し、呼び出し方法をインタフェース化する。これにより整形処理に変更があっても実行クラスへの変更は最小限になる。