0

我正在学习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;
};
4

2 回答 2

4
FirstDecoratorType firstDynamicDec (SecondConcreteType()); 

问题在于它没有定义对象。相反,它声明了一个函数。在这个站点上查找most-vexing-parse in C++,你会得到很多关于它的主题。

简短说明:函数名称是firstDynamicDec其返回类型FirstDecoratorType,它带有参数,它又是一个返回SecondConcreteType且不带参数的函数。

于 2013-01-05T16:05:23.490 回答
1

第一个问题是

FirstDecoratorType firstDynamicDec (SecondConcreteType()); 

根本没有声明一个对象,而是一个函数。这被称为C++ 中最令人头疼的解析

但是,即使您解决了这个问题,您也会遇到临时对象(例如 created by SecondConcreteTpe())仅在表达式结束之前存在的问题,因此FirstDecoratorType在您可以对其进行任何有用的操作之前,其中的指针将是无效的。
您可以通过使用智能指针在装饰器中保存装饰类型来解决此问题(例如,std::unique_ptr)。这使得装饰器负责清理被装饰的类型。

于 2013-01-05T16:10:52.940 回答