FizzBuzzをオブジェクト指向的にやってみた
Qiita始めました
記念すべき初投稿は読んで字の如くです。コロナで籠らざる得なくなった時にポリモーフィズムを勉強したので自分なりのアウトプットしようと思い立ちました。間違っていたり考えが浅かったりするかもしれませんがご愛敬です。
やってみる前に
FizzBuzzとは
英語圏せんだみつおゲームの様なもの
数人で数字を読み上げていき
3で割れる数字は「Fizz」
5で割れる数字は「Buzz」
3でも5でも割れる数字は「FizzBuzz」
を数字の代わりに読み上げる
詰まったり言い淀んだら負けという暇つぶしに丁度良さげな難度のゲームです。
先人達はこの題材で色々な縛りを課してプログラミングするみたいですが今回は特に縛りはありません。強いて言うならオブジェクト指向的にプログラミングしていきます。
オブジェクト指向的にとは
オブジェクト指向 ≒ 値や処理の塊を人の理解できる形にする表現方法
と自分は解釈しています。そのことを反映してプログラミングしていきます。
今回はJavaを使いFizzBuzzというゲームを表現してみたいと思います。
やってみよう
メイン
public class Main {
public static void main(String[] args) {
Game fizzBuzzGame = new Game();
fizzBuzzGame.setCount(20);
fizzBuzzGame.start();
}
}
これだけです。ゲームクラスを呼び出しそのインスタンスに対して数を設定し開始する。
実行すると以下の出力が取れます。
GameStart!!
1
2
Fizz!
4
Buzz!
Fizz!
7
8
Fizz!
Buzz!
11
Fizz!
13
14
FizzBuzz!
16
17
Fizz!
19
Buzz!
うまくいってそうですね。
注目点はメインではゲームクラスを扱うだけで全て終わらせている事です。コードを見辛くするif文やfor文は登場しません。
ゲームクラス
class Game {
private int count;
public void setCount(int count) {
this.count = count;
}
public void start() {
System.out.println("GameStart!!");
for (int i = 1; i <= count; i++) {
System.out.println(FizzBuzzBase.fizzBuzzCreate(i).call);
}
}
}
先程扱ったゲームクラスです。こちらは内部変数としてint型のcount
とそのセッター、スタートメソッドを持ちます。クライアントで扱う部分のクラスになります。
スタートメソッドは開始の合図とcount
変数分System.out.println
を実行します。
注目点はスタートメソッド内のfor文のprintln内の部分になりますが下記のFizzBuzzクラスで解説します。
FizzBuzzクラス
abstract class FizzBuzzBase {
protected String call ;
public static FizzBuzzBase fizzBuzzCreate(int i) {
if( i%3 == 0 && i%5 == 0){
return new FizzBuzz();
}else if(i%3==0){
return new Fizz();
}else if(i%5==0){
return new Buzz();
}
return new Normal(i);
}
}
抽象クラスFizzBuzzBaseです。実装クラスの継承元となります。
クラス内変数call
を持ちます。実装クラスで持つか悩みましたがcount
に対して返すクラス1つなのでクラス内変数で1つ持てばいいかと思いこの形になりました。
もう一つは静的メソッド fizzBuzzCreate
です。これは実装クラスのファクトリーメソッドです。継承した4つの実装クラスのうちどれかを返します。どの条件にも当てはまらない場合Normal
クラスを返します。この部分の条件式がFizzBuzzのルールの部分となります。
class Fizz extends FizzBuzzBase{
Fizz(){
call="Fizz!";
}
}
class Buzz extends FizzBuzzBase{
Buzz(){
call="Buzz!";
}
}
class FizzBuzz extends FizzBuzzBase{
FizzBuzz(){
call="FizzBuzz!";
}
}
class Normal extends FizzBuzzBase{
Normal(int i){
call= String.valueOf(i);
}
}
抽象クラスFizzBuzzBaseを継承した各クラス
- Fizz
- Buzz
- FizzBuzz
- Normal
実装クラスはコンストラクタのみ用意されその中でクラスに応じた文字列をcall
変数へ代入します。
後は呼び出しもとでcall変数を読み出せば先程の出力が得られます。これでオブジェクト指向っぽく?完成です。
System.out.println(FizzBuzzBase.fizzBuzzCreate(i).call);
やってみて
普通にif文書けばよくね?
普通に書けばif文を書いて終わりのところをこねくり回したのでコード量がかなり増えましたね(汗)
シンプルなルールなので現状だとオブジェクトで扱うことの良さが紹介できなかった気がします。でも扱ってみると面白いです多態性。ポリモーフィズム万歳!
お付き合いいただいてありがとうございます。お疲れ様でした。