Head First Design Patterns bookからデコレータ パターンを学んでいます。パターンを機能させるためにコーディングしたもの (C++) は次のとおりです。
#include <iostream>
class AbstractType
{
public:
virtual double value() const = 0;
};
class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};
class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};
class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;
public:
DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject)
{}
DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject)
{}
virtual double value() const = 0;
const AbstractType& getObject() const
{
return *decoratedObject_;
}
};
class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
double value() const
{
const AbstractType& object = getObject();
return 1 + object.value();
}
};
class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
double value() const
{
const AbstractType& object = getObject();
return 2 + object.value();
}
};
using namespace std;
int main()
{
// When I decorate sequentially, it works fine
SecondConcreteType secondConc;
FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;
SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;
FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;
// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
//FirstDecoratorType firstDynamicDec (SecondConcreteType());
//cout << firstDynamicDec.value() << endl;
return 0;
};
メイン プログラムでは、最初に ConcreteType のオブジェクトを作成する必要があります。次に、(DecoratorType 内の) AbstractType へのポインターの構成を使用して装飾します。具体的なオブジェクトを作成し、新しい装飾されたオブジェクトを次々と作成すると、うまく機能します..
DecoratorType が 1 行のコード (サンプル コードのコメント アウトされた行) でコンポジションを使用してオブジェクトを装飾できるようにするには、何をする必要がありますか? このようなものは、「現実の世界」でまったく役に立ちますか? 私は(明らかに)デザインパターンを使用した経験があまりありません..なので、どの機能を目指すべきかを理解するのは難しいです.
編集:
以下は、基本的なポインターで動作するバージョンです (valgrind はメモリ リークを示さず、メモリ リークが発生する可能性はないと述べています)。
#include <iostream>
class AbstractType
{
public:
virtual double value() const = 0;
virtual ~AbstractType() {};
};
class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};
class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};
class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;
bool own_;
public:
DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject),
own_(false)
{}
DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject),
own_(false)
{}
DecoratorType (AbstractType* abstractPtr)
:
decoratedObject_(abstractPtr),
own_(true)
{}
DecoratorType (DecoratorType* decoratorPtr)
:
decoratedObject_(decoratorPtr),
own_(true)
{}
virtual ~DecoratorType()
{
if (own_)
{
delete decoratedObject_;
decoratedObject_ = 0;
}
}
virtual double value() const = 0;
const AbstractType& getObject() const
{
return *decoratedObject_;
}
};
class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
FirstDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}
FirstDecoratorType (FirstDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}
double value() const
{
const AbstractType& object = getObject();
return 1 + object.value();
}
};
class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
SecondDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}
SecondDecoratorType (SecondDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}
double value() const
{
const AbstractType& object = getObject();
return 2 + object.value();
}
};
using namespace std;
int main()
{
// When I decorate sequentially, it works fine
SecondConcreteType secondConc;
FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;
SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;
FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;
// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
FirstDecoratorType firstDynamicDec (new SecondDecoratorType (
new FirstDecoratorType (new SecondConcreteType())));
cout << firstDynamicDec.value() << endl;
return 0;
};