Explanation of the decoration mode of the C ++ Design Mode

Source: Internet
Author: User

Explanation of the decoration mode of the C ++ Design Mode
Decoration mode of C ++ Design Mode

By dynamically adding some additional responsibilities to an object, the decoration mode is more flexible than the subclass generation. The decoration mode is an object structure mode.

I. Reasons

We often add functions to an existing class by means of inheritance, but the inheritance method has significant limitations because

Inheritance is a type of invasive inheritance. is aIs highly coupled and difficult to reuse code.

For example, in the window control, to add new functions, such as adding a scroll bar, adding a background image, and adding new functions through inheritance, there are the following solutions.

We can see that in this solutionScrollAndBckGndThe function is implemented three times. The root cause is that inheritance is a strongly coupled relationship and we cannotBckGndTextBoxInBckGndPartialListBox. So we look forward to a model that canNew functions can be conveniently added like inheritance, and code can be conveniently reused., This mode actually exists-Decoration Mode.

II. Implementation

In fact, the design concept of the decoration mode is very simple, that is, to use aggregation to aggregate the classes to be added to the class for adding functions,Decoration ModeSame name,Wrap the decorated class with a new class.
Suppose we call the class that needs to be decorated (add function)ComponentThe class used for decoration (adding functions) is calledDecorator. In this way, we needDecoratorInternally aggregatesComponentAnd then combine the New and Old functions into a call chain. The code is roughly as follows:

class Component {public:  Component (){};  virtual ~Component ();  virtual void operate(){};};class Decorator {private:  Component* component;  void addOperate():public:  Decorator (Component* c):component(c){};  virtual ~Decorator ();  virtual void operate(){      addOperate();      component->operate()  }};

Now we haveComponentClass, but the problem is obvious.DecoratorIt cannot be used in the originalComponent. OK.DecoratorBecomeComponentClass to solve this problem. The code is modified as follows:

class Component {public:  Component (){};  virtual ~Component ();  virtual void operate(){};};class Decorator : public Component{private:  Component* component;  void addOperate():public:  Decorator (Component* c):component(c){};  virtual ~Decorator ();  virtual void operate() override{      addOperate();      component->operate()  }};int main(){    Component *A = new Component;    Component *B = new Decorator(A);    Component *C = new Decorator(B);    Component *D = new Decorator(C);    Component *E = new Decorator(D);    Component *F = new Decorator(E);    F->operate();}

But the problem arises again. How can we flexibly change the new features to be added? That isaddOperate? We canaddOperateWrite a virtual function to postpone this responsibility to the subclass. The modified code is as follows (Code 1):

Class Component {public: Component () {}; virtual ~ Component () {}; virtual void operate () {std: cout <"Component: operate" <std: endl ;}; class Decorator: public Component {private: Component * component; protected: virtual void addOperate () {}; public: Decorator (Component * c): component (c) {}; virtual ~ Decorator () {}; virtual void operate () override {addOperate (); component-> operate () ;}}; class DecoratorB: public Decorator {protected: virtual void addOperate () override {std: cout <"DecoratorB: addOperate" <std: endl ;}; public: DecoratorB (Component * c): Decorator (c ){}; virtual ~ DecoratorB () {};}; class DecoratorA: public Decorator {protected: virtual void addOperate () override {std: cout <"DecoratorA: addOperate" <std :: endl ;}; public: DecoratorA (Component * c): Decorator (c) {}; virtual ~ DecoratorA () {};}; int main () {Component * A = new Component; Component * B = new DecoratorA (A); Component * C = new DecoratorB (B ); component * D = new DecoratorA (C); Component * E = new DecoratorB (D); Component * F = new DecoratorA (E); F-> operate ();} running result: DecoratorA: addOperateDecoratorB: addOperateDecoratorA: addOperateComponent: operate

It is inconvenient because the parent classDecoratorInterface specified inaddOperateThe subclass does not want to use this interface as the new function to add. If the subclass needs to addaddStateAndaddCounterAnd so on? Subclass must be implementedaddStateAndaddCounterThen useaddOperateCall these two methods.addOperateThe Declaration is also postponed to the subclass so that the subclass determines what this interface is, but it is postponed.addOperateThe statement will inevitably delay the call to it.virtual void operate. The modified code is as follows (Code 2):

class Component {public:    Component (){};    virtual ~Component (){};    virtual void operate(){        std::cout << "Component::operate" << std::endl;    }};class Decorator : public Component{private:    Component *_component;public:    Decorator (Component *C):_component(C){}    virtual ~Decorator (){delete _component;}    virtual void operate() override {        _component->operate();    }};class DecoratorA : public Decorator{private:    void addBehave(){        std::cout << "DecoratorA:addBehave" << std::endl;    }public:    DecoratorA(Component *D):Decorator(D){}    virtual void operate () override{        Decorator::operate();        addBehave();    }};class DecoratorB : public Decorator{private:    void addBehave(){        std::cout << "DecoratorB:addBehave" << std::endl;    }public:    DecoratorB(Component *D):Decorator(D){}    virtual void operate () override{        Decorator::operate();        addBehave();    }};

The above code isDecoration ModeSample Code. Code 2 is the "Orthodox" decoration mode implementation, but I personally prefer the implementation in code 1, because when adding new features, you do not need to modifyoperateMethod, the method provided to the outside is fixed early. The smaller the subclass changes it, the lower the chance of error.

Iii. UML class diagram

The following describes the overall scheme of the decoration pattern class diagram and Widget.

Iv. Summary

Benefits of the decoration mode:

It can expand the functions of an object without inheritance, which is very convenient and flexible. Without a large increase in the number of classes, it can dynamically expand the functions of objects. The specific component classes and decorative classes can be changed independently, when new features are added, you do not need to modify the existing classes, which complies with the open and closed principles.

Disadvantages of the decoration mode:

The logic is more complex than inheritance, and the error possibility is greater than inheritance.

Applicable scenarios of the decoration mode:

When you need to dynamically expand the functions of objects, you cannot use inheritance to add new functions.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.