PythonのSingletonデザインパターン

この記事では、Pythonで実装されたSingleton Design Patternについて説明します。

時代が進むにつれて、ソフトウェアは様々な領域で特定の問題を解決するためにカスタマイズされるようになりました。ソフトウェアのアプリケーションレベルには多くの違いがありますが、ソフトウェア設計のいくつかの側面はほとんど同じままです。これらの側面は、世の中のすべてのソフトウェアに共通するものではないかもしれませんが、多くのシナリオに当てはまると思われます。したがって、これらの側面を学び、理解することは、弾力性のあるプログラムを構築する上で非常に有益です。

今回は、Pythonのデザインパターンと、ソフトウェアを構築するために利用できる様々なパターンについてのシリーズの第一回目です。

デザインパターンとは?

デザインパターンは、ソフトウェア開発において繰り返し発生する問題を解決するための特定のアプローチであり、グッドプラクティスを表すのにも使われます。実際のコードではありませんが、推奨される方法で望ましい解決策を生み出すためにコードを組織化する特定の方法を表します。つまり、すべてのコードに対して決められたデザインパターンに厳密に従う必要はなく、ニーズを分析し、そのニーズに最適なデザインパターンを適用するのである。

デザインパターンは、ソフトウェア開発における問題解決の豊富な経験から生まれ、特定のシナリオに適合するように試行錯誤を繰り返しています。また、デザインパターンを学ぶもう一つの理由は、あるパターンが特定のシナリオで機能しないかもしれないが、解決策を策定するためのベースを提供することができることである。

しかし、デザイン・パターンがさまざまな状況から抜け出す手助けをしてくれるのと同様に、より良い解決策があるかもしれないので、パターンに直接飛びつく前に、現状を評価し、利用できるすべての選択肢を検討することが重要です。

このような場合、「Security(セキュリティ)」と「Behavioral(ビヘイビア)」の2つのパターンに分類されます。

クリエイション・パターン

デザインパターンには、デザインパターンの複雑さ、システム内のアプリケーションレベル、詳細さの量など、互いに異なるいくつかの側面がある。

このような場合、「Creational Pattern」(創造的パターン)は、アプリケーション全体を通してコードの柔軟性と再利用性を高めるのに貢献するオブジェクトを作成する方法を定義するものである。

Creationalパターンの例としては、Singletonパターン、Factory Method、Abstract Factory、Builderパターン、Prototypeパターンがある。

シングルトン・パターン

定義

singletonパターンは、クラスの単一のインスタンスの作成を定義するために使用される一般的な作成パターンであり、そのオブジェクトへの単一のグローバルアクセスポイントを提供します。

このパターンは、クラスから作成できるオブジェクトの数を、アプリケーションでグローバルに共有されることが多い1つのオブジェクトに制限します。

モチベーション

このパターンは、データベース接続やファイルなどの共有リソースへのアクセス制御を必要とする機能でよく実装されます。クラスが単一のインスタンスを作成するためにのみ使用できることを保証し、単一のグローバルアクセスポイントを提供することによって、共有リソースへのアクセスを制限し、整合性を維持することができる。

また、単一インスタンスを生成することで、プログラムの一部が他のクラスによって上書きされ、安全でないコードや非効率なコードにならないようにすることができます。また、同じオブジェクトを複数の箇所でアクセスする場合にも、プログラムのどこかで上書きされる心配がありません。

例えば、データベースへの接続はプログラムの中で一度だけ行われ、アプリケーションの至る所で同じオブジェクトを使ってデータベースに対する操作を行うことができます。もし、アプリケーションの様々な部分が独自のデータベース接続を作成することができれば、各部分が独自にデータベースにアクセスしようとするため、時間の経過とともに整合性の問題が発生する可能性があります。

実装

Singletonパターンは、クラスのインスタンス化を1つのオブジェクトだけに制限することを要求しています。オブジェクトの生成の制御は、生成されたオブジェクトを静的フィールドに保存する生成メソッドを実装することで実現されます。

この作成メソッドを呼び出すと、元のシングルトン・オブジェクトが返されるか、インスタンス化されたオブジェクトが存在することを示すエラーが返されるかのどちらかです。これにより、このクラスで複数のオブジェクトが作成されることを防ぎ、シングルトンプロパティを維持することができます。

シングルトンパターンの良い例として、ある国が、その国へのアクセスや運営をコントロールする単一の政府を持つことができる、というものがあります。別の政府を作ろうとすることは禁じられている。

この政府のアナロジーをシングルトンクラスで実装すると、Pythonでは以下のようになる。

class SingletonGovt:
   __instance__ = None


def __init__(self):
       """ Constructor.
       """
       if SingletonGovt.__instance__ is None:
           SingletonGovt.__instance__ = self
       else:
           raise Exception("You cannot create another SingletonGovt class")


@staticmethod
   def get_instance():
       """ Static method to fetch the current instance.
       """
       if not SingletonGovt.__instance__:
           SingletonGovt()
       return SingletonGovt.__instance__


この例では、インスタンス化される単一のオブジェクトを格納する変数を定義しています。コンストラクタは既存のクラスがあるかどうかをチェックし、エラーを発生させます。

get_instance()` メソッドでオブジェクトを取得する際には、既存のインスタンスがあるかどうかをチェックし、それを返します。もしなければ、インスタンスを生成してそれを返します。

私たちの SingletonGovt が動作している様子です。

government = SingletonGovt()
print(government)


same_government = SingletonGovt.get_instance()
print(same_government)


another_government = SingletonGovt.get_instance()
print(another_government)


new_government = SingletonGovt()
print(new_government)


このスクリプトを実行すると、メモリの一点に SingletonGovt インスタンスが一つだけ格納されていることがわかります。別の政府を作ろうとすると、例外が発生して阻止されます。

長所と短所

プロフェッショナル

  • Singletonパターンは、クラスのインスタンスが1つしか存在しないことを保証するものであり、プログラムにおける予期せぬ動作のリスクを軽減します。
  • クラスの作成は1つのクラスで制御されるため、変更は1つのクラスとオブジェクトに対してのみ行えばよいので、柔軟性がある。

短所

  • シングルトンパターンで作成されたクラスは、単一責任原則に違反する。
  • アプリケーションのライフサイクルの間、シングルトンクラスは生き続け、異なるテストケースはクラスの新しいバージョンを必要とするかもしれないので、ライフサイクル管理は、テストのような他の分野で問題を引き起こす可能性があります。

結論

この記事では、シングルトンデザインパターンを紹介し、議論し、実装してきました。

他のデザインパターンと同様に、このパターンにも長所と短所があり、ある状況には適しているかもしれませんが、すべての開発ニーズに適用できるわけではありません。したがって、目の前の問題を分析し、シングルトンパターンが私たちの仕事を容易にするかどうかを判断するのは私たち次第なのです。

タイトルとURLをコピーしました