【ITニュース解説】Decorator Design Pattern in Python

2025年09月07日に「Dev.to」が公開したITニュース「Decorator Design Pattern in Python」について初心者にもわかりやすいように丁寧に解説しています。

作成日: 更新日:

ITニュース概要

Decoratorパターンは、オブジェクトに動的に機能を追加する設計手法。継承よりも柔軟で、実行時に機能拡張できる。元のクラスをDecoratorクラスで包み、必要なメソッドをオーバーライドして機能を追加。複数のDecoratorを重ねることで、機能の多層的な拡張も可能になる。Pythonでの実装例では、教師クラスをDecoratorで拡張し、専門分野の教師として機能を追加している。

出典: Decorator Design Pattern in Python | Dev.to公開日:

ITニュース解説

デコレーターデザインパターンは、オブジェクト指向プログラミングにおいて、既存のオブジェクトに動的に新しい機能を追加するための便利な方法だ。これは、同じクラスの他のオブジェクトに影響を与えることなく、特定のオブジェクトの振る舞いを変更したい場合に特に有効となる。

このパターンが解決する主な問題は二つある。一つは、オブジェクトの責務(機能)を実行時に動的に追加または削除したい場合。もう一つは、機能拡張のためにサブクラスを作成するよりも柔軟な方法が必要な場合だ。サブクラスを使うと、拡張はコンパイル時にクラスに固定されてしまい、実行時に変更することができない。しかし、デコレーターパターンを使えば、オブジェクトの機能を静的にも動的にも拡張できる。

デコレーターパターンを実現するには、まず元のクラスをラップする新しい「Decorator」クラスを設計する。具体的には、以下の手順で実装する。まず、元のクラス(Componentクラス)を継承してDecoratorクラスを作成する。次に、Decoratorクラスに、Componentクラスの参照を属性として追加する。そして、Decoratorクラスのコンストラクタで、Componentオブジェクトを受け取り、その属性を初期化する。Decoratorクラスでは、ComponentクラスのすべてのメソッドをComponentオブジェクトに転送する。最後に、具体的なDecoratorクラス(ConcreteDecoratorクラス)では、変更したいComponentクラスのメソッドをオーバーライドする。

このパターンは、複数のデコレーターを積み重ねて、オーバーライドされたメソッドに新しい機能を次々と追加できるように設計されている。重要な点として、デコレーターと元のクラスのオブジェクトは、共通の機能セットを共有している。

記事で示されているPythonのソースコードを見てみよう。まず、Teacherという抽象クラスが定義されている。このクラスは、calculate_salary(給与計算)とdo_work(仕事をする)という二つの抽象メソッドを持つ。次に、BasicTeacherクラスがTeacherクラスを継承しており、基本的な教師の機能を実装している。BasicTeacherは、base_salary(基本給)を初期化し、calculate_salaryメソッドで基本給を返し、do_workメソッドで「私は基本的な教師です。一般的な教育活動を行います。」というメッセージを表示する。

次に、デコレーターの役割を果たすSpecialistTeacherクラスが定義されている。このクラスは、Teacherクラスを継承し、別のTeacherオブジェクトをラップする。SpecialistTeacherクラスのコンストラクタは、ラップするTeacherオブジェクトを受け取り、calculate_salaryメソッドとdo_workメソッドは、ラップされたTeacherオブジェクトの対応するメソッドを呼び出す。

さらに、SpecialistPhysicsTeacherSpecialistMathsTeacherSpecialistChemistryTeacherという具体的なデコレータークラスが定義されている。これらのクラスは、SpecialistTeacherクラスを継承し、特定の専門分野の教師の機能を追加する。例えば、SpecialistPhysicsTeacherクラスは、calculate_salaryメソッドをオーバーライドして、基本給に8000円を加算し、do_workメソッドをオーバーライドして、物理の授業を行うことを示すメッセージを表示する。他の専門分野の教師も同様に、給与にそれぞれの金額を加算し、それぞれの専門分野のメッセージを表示する。

メインの実行部分では、まず基本給10000円の物理専門の教師が作成される。SpecialistPhysicsTeacherオブジェクトは、BasicTeacherオブジェクトをラップしている。do_workメソッドが呼び出されると、「私は基本的な教師です。一般的な教育活動を行います。」というメッセージと「私は物理専門の教師です。物理を教えます。」というメッセージが表示される。calculate_salaryメソッドが呼び出されると、18000円(基本給10000円 + 物理専門手当8000円)が返される。

次に、物理と数学の両方を専門とする教師が作成される。この場合、SpecialistMathsTeacherオブジェクトがSpecialistPhysicsTeacherオブジェクトをラップし、さらにSpecialistPhysicsTeacherオブジェクトがBasicTeacherオブジェクトをラップしている。do_workメソッドが呼び出されると、「私は基本的な教師です。一般的な教育活動を行います。」、「私は物理専門の教師です。物理を教えます。」、そして「私は数学専門の教師です。数学を教えます。」というメッセージが表示される。calculate_salaryメソッドが呼び出されると、28000円(基本給10000円 + 物理専門手当8000円 + 数学専門手当10000円)が返される。

このように、デコレーターパターンを使用することで、既存のオブジェクトに動的に機能を追加し、柔軟な拡張を可能にしている。このパターンは、オブジェクト指向プログラミングにおいて非常に強力なツールとなり得る。

関連コンテンツ