이번에는 데코레이터 패턴.

처음 공부했을 때는 우와, 신박하다! 라고 생각했는데, 음.. 꾸며주기 위해 많은 생성자가 불린다는 점이 조금 거슬린다.. 디자인 패턴 자체가 성능이 우선시 된다기보단 추상화와 의존성에 치중하는 것이긴 하지만.



- 객체에 추가적으로 무언가를 ‘동적으로’ 첨가한다.

장점 1. 서브클래스만 추가하면 런타임시 쉽게 객체에 추가할 수 있으므로 유연하다.

장점 2. 데코레이터를 추가하는 부분이 꽤 직관적이라서 가독성이 좋은 것 같다.



자 그럼 예제.

// 장비를 위한 상위 추상 클래스
class Equipment{
public:
    virtual ~Equipment() = 0;
    virtual std::string explain() = 0;
};
Equipment::~Equipment(){}

// 실제 장비를 하는 객체의 추상 클래스
class EquipInstance : public Equipment{
public:
    EquipInstance(const std::string &expl) : _explain(expl) {}
    virtual ~EquipInstance() = 0;
    
    std::string explain() override{
        return _explain;
    }
private:
    std::string _explain;
};
EquipInstance::~EquipInstance(){}

// 장비 객체를 꾸며주는 데코레이터 추상 클래스
class EquipDecorator : public Equipment{
public:
    EquipDecorator(const std::shared_ptr<Equipment> &e) : _parent(e) {};
    virtual ~EquipDecorator() = 0;
    
    std::string explain() override{
        return _parent->explain() + " '" + _partExplain + "'";
    }
protected:
    void setPartExplain(const std::string &partExpl){
        this->_partExplain = partExpl;
    }
private:
    std::shared_ptr<Equipment> _parent;
    std::string _partExplain;
};
EquipDecorator::~EquipDecorator(){}

// 장비 객체 자식 클래스
class HumanEquip : public EquipInstance{
public:
    HumanEquip(const std::string &expl) : EquipInstance(expl) {}
    ~HumanEquip(){}
};
// 데코레이터 자식 클래스 1
class SwordDeco : public EquipDecorator{
public:
    SwordDeco(const std::shared_ptr<Equipment> &e) : EquipDecorator(e) {
        setPartExplain("Swrod");
    }
    ~SwordDeco() {}
};
// 데코레이터 자식 클래스 2
class ShildDeco : public EquipDecorator{
public:
    ShildDeco(const std::shared_ptr<Equipment> &e) : EquipDecorator(e) {
        setPartExplain("Shild");
    }
    ~ShildDeco() {}

}

int main()
{
    std::shared_ptr<Equipment> humanEquip(new HumanEquip("Swordman's Equip"));
    humanEquip = std::shared_ptr<Equipment>(new SwordDeco(humanEquip));
    humanEquip = std::shared_ptr<Equipment>(new ShildDeco(humanEquip));
    
    cout << humanEquip->explain() << endl;
    
    return 0;
}