我正在学习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的对象,然后使用指向AbstractType的指针(在DecoratorType中)的组合来装饰它。它工作正常,如果我创建具体对象,并一个接一个地创建新的装饰对象..
为了让DecoratorType能够使用单行代码中的合成来装饰对象(示例代码中注释掉的行),我需要做些什么?这样的事情在“现实世界”中会有用吗?我(显然)在使用设计模式方面没有太多经验。所以我很难看到我应该瞄准的功能。
编辑:
这是一个使用基本指针的版本(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;
};
答案 0 :(得分:4)
FirstDecoratorType firstDynamicDec (SecondConcreteType());
这个问题是它没有定义一个对象。相反,它声明一个函数。在这个网站上查找C ++中的 most-vexing-parse ,你会得到很多关于它的主题。
简短说明:函数名称为firstDynamicDec
,其返回类型为FirstDecoratorType
,它接受的参数又是一个返回SecondConcreteType
且不带参数的函数。
答案 1 :(得分:1)
第一个问题是
FirstDecoratorType firstDynamicDec (SecondConcreteType());
根本不会声明一个对象,而是一个函数。这称为C ++的most vexing parse。
但即使你解决了这个问题,你也会遇到临时对象(例如SecondConcreteTpe()
创建的)仅存在于表达式结尾之前的问题,因此FirstDecoratorType
中的指针无效在你做任何有用的事情之前。
您可以使用智能指针在装饰器中保存装饰类型来解决此问题(例如,std::unique_ptr
)。这使得装饰者负责清理装饰类型。