Interfaceを使用してSwitch文の保守性を上げる

interfaceを使用して、Switch文を多用したコードの可読性を上げる方法を記載します。

### サンプルコード

ワンちゃんの種類に応じて、可愛さ、攻撃力、知名度を返す関数を考えます。
ワンちゃんの種類は`DogType`のEnumに定義し、`Dog`クラスの各関数がそれぞれ値を返します。

```DogType.java
package org.example.interfaceExample;

public enum DogType {
    kyabaria,
    tiwawa,
    doberman
}
```

```Dog.java

package org.example.interfaceExample;

public class Dog {
    public int cutePoint(DogType dogType) {
        switch (dogType) {
            case tiwawa -> {
                return 5;
            }
            case kyabaria -> {
                return 100;
            }
            case doberman -> {
                return 1;
            }
            default -> {
                return 0;
            }
        }
    }

    public int attackPoint(DogType dogType)  {
        switch (dogType) {
            case tiwawa -> {
                return 2;
            }
            case kyabaria -> {
                return -50;
            }
            case doberman -> {
                return 1000;
            }
            default -> {
                return 0;
            }
        }
    }

    public int popularity(DogType dogType) {
        switch (dogType) {
            case tiwawa -> {
                return 1000;
            }
            case kyabaria -> {
                return 1;
            }
            case doberman -> {
                return 20;
            }
            default -> {
                return 0;
            }
        }
    }
}


```


```Main.java
package org.example;

import org.example.interfaceExample.Dog;
import org.example.interfaceExample.DogType;
import org.example.voExample.*;

import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        var dog = new Dog();
        System.out.println("kyabaria cutePoint " + dog.cutePoint(DogType.kyabaria));
        System.out.println("kyabaria attackPoint " + dog.attackPoint(DogType.kyabaria));
        System.out.println("tiwawa cutePoint " + dog.cutePoint(DogType.tiwawa));
    }
}

```

``` 実行結果
kyabaria cutePoint 100
kyabaria attackPoint -50
tiwawa cutePoint 5
```

上記プログラムは動作しますが、保守性を考えると問題があります。まず3つの関数にSwitch文が重複しています。また犬の種類が追加された際には`DogType`に追加された際には、各関数にそれぞれパターンを追加しないといけませんが、うっかり忘れる可能性があります。これらの問題をinterfaceを使用する事で解消することが出来ます。


まず`Dog`interfaceを作成し、必要な関数を定義します。

```Dog.java
package org.example.interfaceExample;

public interface Dog {
    int cutePoint();
    int attackPoint();
    int popularity();
    String name();
}

```
次に犬の種類ごとにクラスを作成し、`Dog`interfaceを実装するようにします。

```Kyabaria.java
package org.example.interfaceExample;

public class Kyabaria implements Dog{

    @Override
    public int cutePoint() {
        return 100;
    }

    @Override
    public int attackPoint() {
        return -50;
    }

    @Override
    public int popularity() {
        return 1;
    }

    @Override
    public String name() {
        return "kyabaria";
    }
}

```

```Tiwawa.java
package org.example.interfaceExample;

public class Tiwawa implements Dog{
    @Override
    public int cutePoint() {
        return 5;
    }

    @Override
    public int attackPoint() {
        return 2;
    }

    @Override
    public int popularity() {
        return 1000;
    }

    @Override
    public String name() {
        return "tiwawa";
    }
}
```

```Doberman.java
package org.example.interfaceExample;

public class Doberman implements Dog {

    @Override
    public int cutePoint() {
        return 1;
    }

    @Override
    public int attackPoint() {
        return 1000;
    }

    @Override
    public int popularity() {
        return 20;
    }

    @Override
    public String name() {
        return "doberman";
    }
}

```

interfaceを使用する事で、重複したswitchをなくすことができました。また、必要な関数を定義できていない場合には、コンパイラが見つけてくれるようになります。
実際にクラスを使用する場合には次のようになります。

```Main.java
package org.example;
import org.example.interfaceExample.*;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Dog> dogs = List.of(new Kyabaria(), new Tiwawa(), new Doberman());
        dogs.forEach(dog -> {
            System.out.println(dog.name()
                    + " cutePoint " + dog.cutePoint()
                    + " attackPoint " + dog.attackPoint()
                    + " popularity " + dog.popularity());
        });
    }
}
```

`Kyabaria`、`Tiwawa`、`Doberman`を全て同じ`Dog`型として扱っています。このように異なるクラスを同じ型として扱う仕組みを多態といいます。多態を使用する事でswitchなどを用いた条件をすっきりとまとめることができます。