はじめに
最近読んだ、「良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方」という本に以下のような内容が書かれていました。
(この本はかなり良かったのでおすすめです)
「雑にswitch文を書くと、色々なところに同じようなswitch文が書かれることになったり、case文の追加漏れだったりが発生してしまうので、一か所にまとめたり、interfaceを利用した形に置き換えた方が良い」(ざっくりとした要約)
こういった、interfaceを使った書き方のことを「ストラテジパターン」と言い、今まで、switch文の代わりにinterfaceを使う、という考え方・視点でinterfaceを使おうとしたことがなかったので、少し調べて、実際にコードを書いて試してみました。
変更前
・コード
Animalクラスのsound()メソッドにswitch文を使用し、typeの値で処理を変えています。
public class Animal {
final String type;
public Animal(String type) {
this.type = type;
}
public void sound() {
switch (this.type) {
case "dog":
System.out.println("ワン");
break;
case "cat":
System.out.println("ニャー");
break;
default:
System.out.println("エラーです");
}
}
}
import animal.Animal;
public class Main {
public static void main(String[] args) {
Animal dog = new Animal("dog");
dog.sound();
Animal cat = new Animal("cat");
cat.sound();
}
}
変更後
・イメージ図
AnimalStrategyというinterfaceを作成して、それを継承したDogとCatクラスを作成します。
・コード
public interface AnimalStrategy {
public void sound();
}
public class Dog implements AnimalStrategy {
@Override
public void sound() {
System.out.println("ワン");
}
}
public class Cat implements AnimalStrategy {
@Override
public void sound() {
System.out.println("ニャー");
}
}
public class Animal {
final AnimalStrategy animalStrategy;
public Animal(AnimalStrategy animalStrategy) {
this.animalStrategy = animalStrategy;
}
public void sound() {
this.animalStrategy.sound();
}
}
import animal.Animal;
import animal.Cat;
import animal.Dog;
public class Main {
public static void main(String[] args)
Animal dogAnimal = new Animal(new Dog());
dogAnimal.sound();
Animal catAnimal = new Animal(new Cat());
catAnimal.sound();
}
}
作成したinterface(AnimalStrategy)を Animalクラスにプロパティとして持たせ、コンストラクタで受け取る形にします。
Mainクラスで呼び出す際には、最初のインスタンス化時に実際に使用したいクラスを渡します。
確かにこれでswitch文を使わずに、同じ処理のコードが書けました。
おわりに
今回は、本の書き方と異なる形で書いてみました。
Animalクラスみたいなクラスでこれをするのは、少し分かりにくかった気もするので、気になった方は「ストラテジパターン」で調べて、より分かりやすい記事を探してみてください。
今度からswitch文を使う際には、interfaceを使った書き方で置き換えることが可能か、一考してみようと思いました。