シリーズ記事ディレクトリ
C++ スキル シリーズ
Linux 通信アーキテクチャ シリーズ
C++ 高性能最適化プログラミング シリーズ
ソフトウェア アーキテクチャの深い理解設計シリーズ
高度な C++ 同時スレッド プログラミング
設計パターン シリーズ
ご注目をお待ちしております!!!
现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.
構造設計パターンのデコレータパターン
1. デコレーターモードの概要
⚠️ 意图:
追加の責任をオブジェクトに動的に追加します。デコレータ パターンは、機能を追加するという点でサブクラス化よりも柔軟です。
⚠️ 主要解决:
一般に、クラスを拡張するには継承を使用することがよくあります。これは、継承によってクラスに静的な機能が導入され、拡張機能の増加に伴ってサブクラスが拡張されるためです。
⚠️ 何时使用:
多くのサブクラスを追加せずにクラスを拡張します。
⚠️ 如何解决:
デコレータ パターンを継承しながら、特定の機能責任を分割します。
デコレータモードの特徴:
-
装飾されたオブジェクトは、実際のオブジェクトと同じインターフェイスを持ちます。クライアント オブジェクトは、実際のオブジェクトと同じように装飾されたオブジェクトと対話できます。
-
装飾されたオブジェクトには実際のオブジェクトへの参照が含まれています
-
装飾されたオブジェクトはクライアントからのすべてのリクエストを受け入れ、それらを実際のオブジェクトに転送します。
-
装飾されたオブジェクトは、クライアントからのリクエストを転送する前または後に、いくつかの追加機能を追加できます。これにより、実行時に、特定のオブジェクトの構造を変更することなく、追加の機能を外部から追加できるようになります。オブジェクト指向設計では、通常、特定のクラスの機能拡張は継承によって実現されます。既存のクラスを継承することで、サブクラスは独自のメソッドを持ちながら、親クラスのメソッドも持つことができます。ただし、継承は静的であるため、ユーザーは動作をいつどのように追加するかを制御できません。初期化されたオブジェクトの動作を変更したい場合は、実行時にのみ変更できます。多くのクラスの動作を継承したい場合は、多数の異なるクラスが作成される可能性があります。
デコレータ パターンは、サブクラスを変更するための柔軟なソリューションを提供します。デコレーションモードは、元のクラスファイルを変更したり継承を利用したりすることなく、オブジェクトの機能を動的に拡張し、実際のオブジェクトをラッパーオブジェクト(デコレーション)を作成してラップします。
デコレータ パターンは、サブクラスのグループと一緒に使用するとさらに便利です。(親クラスから派生した) サブクラスのファミリーがある場合、サブクラスとは独立して使用するときに機能を追加する必要があります。装飾モードを使用してコードの重複を回避し、特定のサブクラスの数を増やすことができます。
次に、デコレータ モードの長所と短所
2.1 利点
-
静的継承よりも柔軟です。オブジェクトの静的継承 (多重継承) と比較して、デコレータ パターンはオブジェクトに責任を追加するより柔軟な方法を提供します。責任は、デコレータを使用して、add および detach メソッドを使用して実行時に追加および削除できます。継承メカニズムでは、追加された責任ごとに新しいサブクラスを作成する必要があるため、多くの新しいクラスが作成され、システムが複雑になります。さらに、特定の Component クラスに複数の異なる Decorator クラスを提供すると、一部の役割の混合と一致が可能になります。Decorator パターンを使用すると、機能を繰り返し追加するのが簡単です。
-
特性が多すぎる階層の上位レベルのクラスは避けてください。デコレータ パターンは、責任を追加するための「従量課金制」アプローチを提供し、複雑でカスタマイズ可能なクラスで予測可能な特性をすべてサポートしようとするものではありません。代わりに、単純なクラスを定義し、Decorator クラスを使用して関数をその単純なクラスに徐々に追加し、単純なコンポーネントから複雑な関数を組み合わせることができます。
-
元のクラスは、そのクラスの装飾機能をクラスから削除することで簡素化できます。
-
これにより、クラスの中核となる役割が装飾関数から効果的に分離され、関連するクラスで繰り返される装飾ロジックを削除できます。
ビルダー モードでは構築プロセスが安定している必要がありますが、デコレーション モードの構築プロセスは不安定であり、さまざまな組み合わせが考えられます。
2.2 欠点
-
デコレーターはコンポーネントと同じではありません。デコレーターは透明なラッパーです。オブジェクトのアイデンティティの観点から見ると、装飾されたコンポーネントはコンポーネント自体とは異なるため、装飾の使用はオブジェクトのアイデンティティに依存すべきではありません。
-
小さなオブジェクトがたくさんあります。Decorator パターンを使用したシステム設計では、クラスやプロパティ値ではなく、相互の接続方法が異なるだけの類似した小さなオブジェクトが多数生成される傾向があります。これらのシステムは、知識のある人にとっては簡単にカスタマイズできますが、習得が難しく、トラブルシューティングも困難です。
3. デコレーターモードの使用シナリオ
-
他のオブジェクトに影響を与えることなく、動的かつ透過的な方法で個々のオブジェクトに責任を追加します。
-
取り消される可能性のある責任に対処する
-
サブクラスの生成方法を拡張できない場合。状況の 1 つは、多数の独立した拡張機能があり、それぞれの組み合わせをサポートするために多数のサブクラスが生成され、サブクラスの数が爆発的に増加するということです。別の状況としては、クラス定義が非表示になっているか、クラス定義を使用してサブクラスを生成できないことが考えられます。
第四に、デコレータモードの実現
コンポーネント抽象クラス:
#ifndef COMPONENT_H
#define COMPONENT_H
#include <iostream>
using namespace std;
//Component抽象类,定义类对象的接口
class Component
{
public:
virtual ~Component(){
}
virtual void Operation() = 0;
protected:
Component(){
}
};
#endif // COMPONENT_H
ConcreteComponent 固有のオブジェクト クラス:
#ifndef CONCRETECOMPONENT_H
#define CONCRETECOMPONENT_H
#include "Component.h"
//ConcreteComponent:具体的Component对象,可以给对象动态添加职责
class ConcreteComponent : public Component
{
public:
ConcreteComponent(){
}
~ConcreteComponent(){
}
virtual void Operation()
{
cout << "Original:ConcreteComponent::Operation" << endl;
}
};
#endif // CONCRETECOMPONENT_H
デコレータ抽象装飾オブジェクト クラス:
#ifndef DECORATOR_H
#define DECORATOR_H
#include "Component.h"
//Decorator:装饰抽象类,继承自Component
class Decorator : public Component
{
public:
Decorator(Component* com)
{
m_pCom = com;
}
void setComponent(Component* com)
{
m_pCom = com;
}
virtual ~Decorator(){
}
virtual void Operation() = 0;
protected:
Component* m_pCom;
};
#endif // DECORATOR_H
ConcreteDecorator特定の装飾オブジェクト クラス:
#ifndef CONCRETEDECORATORA_H
#define CONCRETEDECORATORA_H
#include "Decorator.h"
//ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
class ConcreteDecoratorA : public Decorator
{
public:
ConcreteDecoratorA(Component* com):Decorator(com)
{
}
~ConcreteDecoratorA(){
}
virtual void Operation()
{
m_pCom->Operation();
//附加职责A
AddBehavorA();
}
void AddBehavorA()
{
cout << "Extra A:ConcreteDecoratorA::AddBehavorA" << endl;
}
};
#endif // CONCRETEDECORATORA_H
ConcreteDecoratorB 固有の装飾オブジェクト クラス:
#ifndef CONCRETEDECORATORB_H
#define CONCRETEDECORATORB_H
#include "Decorator.h"
//ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
class ConcreteDecoratorB : public Decorator
{
public:
ConcreteDecoratorB(Component* com):Decorator(com)
{
}
~ConcreteDecoratorB(){
}
virtual void Operation()
{
m_pCom->Operation();
//附加职责B
AddBehavorB();
}
void AddBehavorB()
{
cout << "Extra B:ConcreteDecoratorB::AddBehavorB" << endl;
}
};
#endif // CONCRETEDECORATORB_H
ConcreteDecoratorC 固有の装飾オブジェクト クラス:
#ifndef CONCRETEDECORATORC_H
#define CONCRETEDECORATORC_H
#include "Decorator.h"
//ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
class ConcreteDecoratorC : public Decorator
{
public:
ConcreteDecoratorC(Component* com):Decorator(com)
{
}
~ConcreteDecoratorC(){
}
virtual void Operation()
{
m_pCom->Operation();
//附加职责C
AddBehavorC();
}
void AddBehavorC()
{
cout << "Extra C:ConcreteDecoratorC::AddBehavorC" << endl;
}
};
#endif // CONCRETEDECORATORC_H
ConcreteDecoratorD 固有の装飾オブジェクト クラス:
#ifndef CONCRETEDECORATORD_H
#define CONCRETEDECORATORD_H
#include "Decorator.h"
//ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能
class ConcreteDecoratorD : public Decorator
{
public:
ConcreteDecoratorD(Component* com):Decorator(com)
{
}
~ConcreteDecoratorD(){
}
virtual void Operation()
{
m_pCom->Operation();
//附加职责D
AddBehavorD();
}
void AddBehavorD()
{
cout << "Extra D:ConcreteDecoratorD::AddBehavorD" << endl;
}
};
#endif // CONCRETEDECORATORD_H
クライアントの発信者:
#include "ConcreteComponent.h"
#include "ConcreteDecoratorA.h"
#include "ConcreteDecoratorB.h"
#include "ConcreteDecoratorC.h"
#include "ConcreteDecoratorD.h"
int main()
{
//要装饰的对象
Component* pCom = new ConcreteComponent();
Decorator* pDec = NULL;
//给装饰对象附加职责A
pDec = new ConcreteDecoratorA(pCom);
//给装饰对象附加职责B
pDec = new ConcreteDecoratorB(pDec);
//给装饰对象附加职责C
pDec = new ConcreteDecoratorC(pDec);
//给装饰对象附加职责D
pDec = new ConcreteDecoratorD(pDec);
pDec->Operation();
delete pCom,pDec;
return 0;
}
5. デコレータモードの応用例
携帯電話の装飾例:
電話の抽象クラス:
#ifndef PHONE_H
#define PHONE_H
#include <iostream>
#include <string>
using namespace std;
//抽象类
class Phone
{
public:
Phone(){
}
virtual ~Phone(){
}
virtual void showDecorator() = 0;
};
#endif // PHONE_H
iPhone の具体的なオブジェクト クラス:
#ifndef IPHONE_H
#define IPHONE_H
#include "Phone.h"
//具体手机类
class iPhone : public Phone
{
public:
iPhone(string name):m_name(name){
}
~iPhone(){
}
void showDecorator()
{
cout << m_name << " 's Decorator" << endl;
}
private:
string m_name;
};
#endif // IPHONE_H
MiPhone 固有のオブジェクト クラス:
#ifndef MIPHONE_H
#define MIPHONE_H
#include "Phone.h"
//具体手机类
class MiPhone : public Phone
{
public:
MiPhone(string name):m_name(name){
}
~MiPhone(){
}
void showDecorator()
{
cout << m_name << " 's Decorator" << endl;
}
private:
string m_name;
};
#endif // MIPHONE_H
DecoratorPhone 装飾基本クラス:
#ifndef DECORATORPHONE_H
#define DECORATORPHONE_H
#include "Phone.h"
//装饰基类
class DecoratorPhone : public Phone
{
public:
DecoratorPhone(Phone* phone):m_phone(phone){
}
~DecoratorPhone(){
}
virtual void showDecorator() = 0;
protected:
Phone* m_phone;//要装饰的对象
};
#endif // DECORATORPHONE_H
DecoratorPhoneA 固有の装飾オブジェクト クラス:
#ifndef DECORATORPHONEA_H
#define DECORATORPHONEA_H
#include "DecoratorPhone.h"
//具体装饰类
class DecoratorPhoneA : public DecoratorPhone
{
public:
DecoratorPhoneA(Phone* phone):DecoratorPhone(phone){
}
void showDecorator()
{
m_phone->showDecorator();
addDecorator();//增加装饰
}
private:
void addDecorator()
{
cout << "add a DecoratorPhoneA Decorator" << endl;
}
};
#endif // DECORATORPHONEA_H
DecoratorPhoneB 固有の装飾オブジェクト クラス:
#ifndef DECORATORPHONEB_H
#define DECORATORPHONEB_H
#include "DecoratorPhone.h"
//具体装饰类
class DecoratorPhoneB : public DecoratorPhone
{
public:
DecoratorPhoneB(Phone* phone):DecoratorPhone(phone){
}
void showDecorator()
{
m_phone->showDecorator();
addDecorator();//增加装饰
}
private:
void addDecorator()
{
cout << "add a DecoratorPhoneB Decorator" << endl;
}
};
#endif // DECORATORPHONEB_H
クライアントの発信者:
#include "Phone.h"
#include "MiPhone.h"
#include "iPhone.h"
#include "DecoratorPhoneA.h"
#include "DecoratorPhoneB.h"
int main()
{
Phone *iphone = new iPhone("iPhone X");
Phone* decorator1 = NULL;
decorator1 = new DecoratorPhoneA(iphone); //增加装饰
decorator1 = new DecoratorPhoneB(decorator1); //增加装饰
decorator1->showDecorator();//显示装饰
Phone *mi = new MiPhone("Mi 6");
Phone* decorator2 = NULL;
decorator2 = new DecoratorPhoneA(mi); //增加装饰
decorator2 = new DecoratorPhoneB(decorator2);//增加装饰
decorator2->showDecorator();//显示装饰
delete decorator2,decorator2;
delete iphone,mi;
return 0;
}