#あすみかんの上にあすみかん

#たのしいことしかかかないことをここに決意します

「オブジェクト指向のこころ」から学ぶSingletonパターン

qiita.com

この記事は「Hamee Advent Calendar 2021」10日目の記事です🙌

10日目

はにゃにゃふわ〜〜〜〜!!!ついに3日目きちゃったナ〜〜
走りきった私スバラ焼肉のタレ〜〜〜!今日は自分の幸せを願うよ〜〜〜!!永遠(とわ)に幸あれ〜〜〜〜〜!!!

前回までのあらすじ

asumikan.hatenablog.com

asumikan.hatenablog.com

※ 前回・前々回の記事を見てない方はそちらから見ていただくといいヤモです❣️点と点が線になってしまう・・・ヤモね❣️(保証なし✋ ")

「Strategyパターン」「Decoratorパターン」を2日に渡ってじっこりと・・・見てきました ( 👁 👄 👁 )それぞれ「振る舞いに関するデザインパターン」と「構造に関するデザインパターン」のうちの1つです。
本日は生成に関する「Singletonパターン」なのですが、、そういえばそれぞれの分類は結局なんなのか?(なんの違いがあるのか?)みたいな部分はあんまり触れてきてなかったな!?となったため、今日はこの分類について再度考察する感じにしていきたいとオムライス〜!


ブログ内でおもに触れている章!

第Ⅶ部 第20章 生成に関するパターンから得られる教訓
第Ⅶ部 第21章 SingletonパターンとDouble-Checked Lockingパターン

尚、ブログではSingletonパターンのみ触れる形とします🌙

「振る舞い」「構造」「生成」

それぞれって結局なんなの?

GoFは概念的な動機に基づき、パターンの分類を行っています。

  • 「振る舞いに関するパターン」は、振る舞いにおける流動的要素を保持させるために使用します。
  • 「構造に関するパターン」は、既存コードを新たなオブジェクト指向設計に統合化する際に有効なものとなります。
  • 「生成に関するパターン」は、オブジェクトの生成を管理する際に有効なものとなります

(p.298 - 20.2 ファクトリ)

より具体的な説明がその先に続いていたのでそちらに続きます👇

新たなオブジェクトを定義する際、それをどのようにしたいのかを定義するには、振る舞いに関するパターンを指針にすることができるでしょう。
(p.298 - 20.2 ファクトリ)

「振る舞い」に関して。
実装をする際にどのようにやり取りをしたいか?させたいか?を考えたときに良く出てきやすいパターンたち。と理解しました。
たとえば、「Strategyパターン」では「任意の同じ責任を持ったものたちがポリモーフィズム的に呼び出せる振る舞い」をさせていたかな、と思います。

既存オブジェクトを新たな設計パラダイムに取り込むのであれば、構造に関するパターンを指針にすることができるはずです。
(p.298 - 20.2 ファクトリ)

「構造」に関して。
既にある既存システムを破壊せずに設計を再構築する、みたいなデザインパターンは「構造」に分類されるのかな、と思いました。
興味・関心が「既存システムの中身」ではなく、「既存システムを組み合わせて出来上がったもの」にありそうです。
「Decoratorパターン」の様々なパーツを組み合わせていくところは、まさに「構造」を作っている部分と言えそうです。(パーツの中身の実装については特に興味がなかったですね!)

最初に、オブジェクトを洗い出し、その動作方法を決定し、その後で、実体化方法を決定するわけです。
(p.299 - 20.3 続・コンテキストを考慮するときの規則)

「生成」に関して。
「振る舞い」や「構造」とは少し毛色が違ったもので、この2つにより、「どのようにプログラムが動くか」が考慮され、それを実態にさせるのが「生成」なのかなと思いました。

「生成/管理」と「使用」

オブジェクトの生成と管理を検討する段階て従うべき一般的な規則があります。それは、「オブジェクトは、他のオブジェクトを生成および/あるいは管理するか、他のオブジェクトを使用するかのどちらかのみを行い、双方を行ってはいけない」というものです。
(p.201 - 20.4 指針に従ったファクトリ)

「一覧は知っているがそれぞれ何をしているかは知らない」「自分の中身はしっているが、並列する概念が何をしているかは知らない」のような言い換えができるのかな、、💭
前者が「生成」でどちらかというと外側の設計に近く、後者が「構造」「振る舞い」で、どちらかというと内側の設計に近そうです。

正しく「生成」されることで、「構造」「振る舞い」たちは自分が仕様通り動くことのみ保証すればいいので、いい感じに責任が分離できますね!🙌
(そう思えば「Configuration」部分とかは若干「生成」に近い振る舞いをしてましたね、、!)

オブジェクト指向のこころ」から学ぶSingletonパターン

さて、そんな「生成」のうちの1つを紹介してきます 🍃
今回のパターンは、顧客からの「新たな要求」によるデザインパターンの適用ではないため、今までのように「課題」「解決法」のような紹介方法ではなく、「どのように実装されるのか?」の観点でご紹介させていただきます!

Singletonパターンで解決したいこと

システム実行時に実体化するオブジェクトの数をたった1つに制限するという規則をカプセル化したものです。
(p.307 - 21.1 概要)

Singletonパターンのような実装をすることで、「同じ意味合いのオブジェクトが複数個できてしまうのを避ける」ことができます💡

コード例

<?php
class USTax extends CalcTax {
    private static $instance;

    private function __construct(){
        echo "new!";
    }

    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new USTax();
        }
        return self::$instance;
    }
}

本ではjavaで書いてありましたが、PHPで書き換えてみました。

  • コンストラクタをprivateで潰す(外部からnewできないように)
  • インスタンスがなければ作り、あれば作らずにそれを返す

今回のUSTaxの「税計算」部分は状況に応じて変わるものではないので、staticのような振る舞いをもっています。そのためSingletonパターンを適用することができるのです💡

「Singletonパターン」は古典的なパターン?

本ブログを書くためにいろいろ検索していると、「Singletonパターン」に関して様々な議論がされているのを発見しました😨!

PHP Mentors — STUPIDなコード

programming-tips.jp

zenn.dev

詳しくは上記の記事等を見て欲しいのですが良くない根拠の1つとして「staticにすることでグローバル汚染じみてしまう」「テストがしにくい」という部分がありました。「た、確かに、、」という気持ちになりました🤤
そもそも「本当に1つにすることで明確なメリットあるの?」みたいな部分はちゃんと考えて使っていく必要がありそうだな、と思いました。
(ある場合もある、その場合は本当に使い所なのだと思う)

3つのデザインパターンに触れてみて 🌸

3日間に渡ってデザインパターンだったりその周辺の知識だったりに触れてきました。その中で、自分の中でアップデートされた知識を最後に書いていきたいと思います 🍀

責任を適切に分けるということ

  • 「Strategyパターン」で「税計算」クラスで分離したり
  • 「Strategyパターン」「Decoratorパターン」で「Configuration」に「生成」の責任をお任せしたり
  • 「生成/管理」と「使用」で分けよーね!ってしたり

も〜〜いろんなところで「責任をわけよ!!」してきました。もうほぼ呼吸のように。責任分離の呼吸❣️「役割を複数もつのはやめよーね!」みたいなアプローチの仕方が、いつ何時でも私たちのそばにいました。
責任を分けることで「凝集度を高める」「それぞれのオブジェクトの依存を薄める」ことができるし、適切に責任が別れていること、これすなわち「オブジェクト指向」なのかな、と自分の中で思いました💘

デザインパターンは常に「正」な訳ではないこと

  • 「Strategyパターン」が適切そうだったのに、じつは「Decoratorパターン」が適切だったり
  • 「Singletonパターン」が使われ方によっては、現在は好ましいと思われてないところだったり

「ケース」によっては普通に悪手になっちゃうこともある、ということはちゃんと認識しておかねば・・・!と肝っ玉を冷やしました。

実は、私は新卒の時に「デザインパターン」の勉強会を同期同士でやっていました。1人1つ回すスタイルで。
オブジェクト指向のこころ」で改めてデザインパターンをやってみて思ったこと。「新卒の頃のワシ、なんもわかってなかったんだな・・・」ということ。
今回、「あっ、そういえばこんなことで悩んだな〜」「こうやって実装すれば良かったのか〜・・・!」と、実際に体験したものと照らし合わせることで本を読み進めていました。今となっては「経験」があるのでその勉強法ができるけど、新卒の頃だとその「経験」がなかったので、多分「ほ〜〜〜ん・・・そすか・・・」程度にしか思えなかったです・・・

結局、どの「ケース」が適しているのか?(=流動的要素はどこなのか?どのように膨らむのか?)を見極めるのは「経験」するしかないのかなーと身もフタもないことを思いました🐱 👉
ただ、こんなのがあったな・・・と「知っている」だけでも大分助けにはなっていたとは思うので、新卒の頃にデザインパターン勉強しといてよかった!🙌

おわりに

いや〜〜〜〜〜〜〜〜〜〜!たのしかった〜〜〜〜〜〜!難しかったけど、たのしかった!です!自分の中のフヤっとした部分を文章で起こせたのはとてもいい経験になりますね、、!
いつもアドベントカレンダーでしかアウトプットできていないのですが、来年は定期的にアウトプットしたいな?というきもちになりました。来年まで持ち越したい気持ちのうちの1つです。

ひろやさん、毎年アドカレ企画ありがとうございます💋
qiita.com

では、また来年お会いしましょう!!!