Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Switch文は増やさない! Strategyパターン & Factory Methodパタ...

suger4
August 24, 2022

Switch文は増やさない! Strategyパターン & Factory Methodパターン 活用術

suger4

August 24, 2022
Tweet

More Decks by suger4

Other Decks in Programming

Transcript

  1. #readablelt 柴田知詩(しばたさとし) 2017年 ラクス入社 - ~2019 楽楽精算 - 2019~ 楽楽明細

    業務内容 - 要件定義~製造~テスト - 運用・リリース - 業務を楽にするツール造り 最近のマイブーム - 自宅いい感じ化 計画 - ニトリ・IKEAに通いがち
  2. #readablelt public void ViewLogic (Auth auth) { switch (auth) {

    case ADMIN: //閲覧+管理者閲覧処理 break; case VIEWER: //閲覧処理 break; } } なんとなく書いてしまうと…… なにやら似たようなswitch文が…… ※Javaイメージのため、   適宜読み替えてください public void RegisterLogic (Auth auth) { switch (auth) { case ADMIN: //登録処理 break; case VIEWER: //閲覧しかできないので権限エラー break; } }
  3. #readablelt /** * ユーザ操作インターフェース **/ interface UserOperation { void 閲覧();

    void 登録(); } ①権限や操作が増える度に、使用箇所を調査しなければならない • ユーザの操作をIF化して、 動きを共通化 ⇒ユーザの操作は本当に 「閲覧・登録」のみと言える。 • 操作が増えるときは、IFを編集する ⇒実装クラスはコンパイルエラーに ◦ 修正漏れを検知可能 /** * 管理者用操作クラス **/ public class AdminOpe implements UserOperation { @Override public void 閲覧() { //閲覧処理 } @Override public void 登録() { //登録処理 } } /** * 閲覧処理クラス **/ public class ViewLogic { public void View(Auth auth) { UserOperation ope //操作クラスを設定 switch (auth) { case ADMIN: ope = new AdminOpe(); break; case VIEWER: ope = new ViewerOpe(); break; } ope.閲覧(); } } ⇒ IFを活用して、状況(権限)によって動きを切り替える   ストラテジーパターン
  4. #readablelt ②権限や操作が増える度に、Switchを編集しなければならない。 • 権限毎にSwitchしているまま ◦ このままでは権限の追加し忘れで修正漏れに… /** * 閲覧処理クラス **/

    public class ViewLogic { public void view(Auth auth) { UserOperation ope //操作クラスを設定 switch (auth) { case ADMIN: ope = new AdminOpe(); break; case VIEWER: ope = new ViewerOpe(); break; } ope.閲覧(); } } /** * 登録処理クラス **/ public class RegisterLogic { public void register(Auth auth) { UserOperation ope //操作クラスを設定 switch (auth) { case ADMIN: ope = new AdminOpe(); break; case VIEWER: ope = new ViewerOpe(); break; } ope.登録(); } }
  5. #readablelt • 操作の切り替えを行う処理を1か所にまとめる。 ◦ 共通IFに対して、どのクラスを利用するのかは、サブクラスに任せる。 ⇒ファクトリメソッドパターン /** * ユーザ操作 Factoryクラス

    **/ public static class UserOpeFactory { public static void GetOpe(Auth auth) { UserOperation ope //権限に応じた 操作クラスを返却 switch (auth) { case ADMIN: return new AdminOpe(); case VIEWER: return new ViewerOpe(); } } } /** * 閲覧処理クラス **/ public class ViewLogic { public void view(Auth auth) { UserOperation ope = UserOpeFactory.GetOpe(auth) ope.閲覧(); } } /** * 登録処理クラス **/ public class RegisterLogic { public void register(Auth auth) { UserOperation ope = UserOpeFactory.GetOpe(auth) ope.登録(); } } ②権限や操作が増える度に、Switchを編集しなければならない。
  6. #readablelt public void ViewLogic(Auth auth) { switch (auth) { case

    ADMIN: //閲覧+管理者閲覧処理 case VIEWER: //閲覧処理 break; } } public void RegisterLogic (Auth auth) { switch (auth) { case ADMIN: //登録処理 break; case VIEWER: //閲覧しかできないので権限エラー break; } } /** * ユーザ操作 Factoryクラス **/ public static class UserOpeFactory { public static void GetOpe(Auth auth) { UserOperation ope //権限に応じた操作クラスを返却 switch (auth) { case ADMIN: return new AdminOpe(); case VIEWER: return new ViewerOpe(); } } } /** * 閲覧処理クラス **/ public class ViewLogic { public void view(Auth auth) { UserOperation ope = UserOpeFactory.GetOpe(auth) ope.閲覧(); } } /** * 登録処理クラス **/ public class RegisterLogic { public void register(Auth auth) { UserOperation ope = UserOpeFactory.GetOpe(auth) ope.登録(); } } /** * ユーザ操作インターフェース **/ interface UserOperation { void 閲覧(); void 登録(); } /** * 管理者用操作クラス **/ public class AdminOpe implements UserOperation { @Override public void 閲覧() { //閲覧処理 } @Override public void 登録() { //登録処理 } } Befor After
  7. #readablelt • ストラテジーパターン ◦ 状況(権限)によって、動きを切り替えるように ◦ 状況毎の動きは1クラス内にまとめられるように。 ◦ IFの実装により、修正漏れを機械的に検知できるように。 •

    ファクトリメソッドパターン ◦ switch文を1か所にまとめることで、メンテナンス性が上がるように。 ◦ 業務の本質的でない処理(切り替え)を別クラスに隠蔽。 まとめ