interface を使う理由 Java
interface を使う理由
実例
- 標準入力した文字列を replace して trim する
interface 利用前
package
src | +- Main.java +- util | +- MyIO.java
Main.java
package src; import src.util.MyIO; public class Main { public static void main(String[] args) { MyIO io = new MyIO(); io.IOStream(); } }
MyIO.java
package src.util; import java.util.*; import java.io.*; public class MyIO { public void IOStream() { try(BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) { while(true) { System.out.println("Input"); String output = stdin.readLine(); output = trimer(replacer(output, "a", "ummm")); System.out.println("Final output is:[" + output + "]"); } } catch(Exception e) { e.printStackTrace(); } } private String replacer(String input, String oldStr, String newStr) { return input.replaceAll(oldStr, newStr); } private String trimer(String input) { return input.trim(); } }
実行例
@ = space. not stdin
Input @he is a ... who?@ Final output is:[he is ummm ... who?]
上述設計での課題
- 機能追加への柔軟性がない
- 機能追加要望が発生した場合
(replacer, trimer 以外に upper を追加など)
private メソッドを増やす必要が有る - MyIO の replace と trim が別クラスでも使われることになった場合
→ replacer と trimer が public になる
→ MyIO クラスが別クラスと密結合になる
→ replacer と trimer を修正する度に、結合クラスへの影響を調べる必要が有る
→ (゚∀゚)
- 機能追加要望が発生した場合
interface 利用後(モジュールが疎結合)
package
src | +- Main.java +- util | +- MyIO.java +- interfaces | +- StringConverter.java +- Replacer.java +- Trimer.java
Main.java
package src; import java.util.*; import src.util.MyIO; import src.interfaces.Replacer; import src.interfaces.Trimer; public class Main { public static void main(String[] args) { MyIO io = new MyIO(Arrays.asList(new Replacer("a", "ah!"), new Trimer()) ); io.IOStream(); } }
MyIO.java
package src.util; import java.util.*; import java.io.*; import src.interfaces.StringConverter; public class MyIO { private final List<StringConverter> converters; public MyIO(List<StringConverter> converters) { this.converters = converters; } public void IOStream() { try(BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in))) { while(true) { System.out.println("Input"); String output = stdin.readLine(); for(StringConverter convert : converters) { output = convert.execConvert(output); } System.out.println("Final output is:[" + output + "]"); } } catch(Exception e) { e.printStackTrace(); } } }
StringConverter.java
package src.interfaces; public interface StringConverter { String execConvert(String input); }
Replacer.java
package src.interfaces; public class Replacer implements StringConverter { private final String oldStr; private final String newStr; public Replacer(String oldStr, String newStr) { this.oldStr = oldStr; this.newStr = newStr; } @Override public String execConvert(String input) { return input.replaceAll(oldStr, newStr); } }
Trimer.java
package src.interfaces; public class Trimer implements StringConverter { @Override public String execConvert(String input) { return input.trim(); } }
実行例
@ = space. not stdin
Input @he is a ... who?@ Final output is:[he is ah! ... who?]
メリット
- (設計上)機能追加しやすい
デメリット
- 機能ごとにファイルが必要になり、冗長性が増す
参考
7章 インターフェース より