I understand the design pattern (C ++ implementation) -- decorator pattern)

Source: Internet
Author: User

Solved problems:

We bought several abstract paintings when decorating our new home. After buying them, we found that some colored borders are more suitable for us, while some of them are more suitable for our use. How can we solve this problem? He needs to dynamically add additional responsibilities to other objects, which is the purpose of the Paster mode.

We can add new functions to the original object by means of inheritance, but the decoration mode is more flexible than the subclass generation by means of combination.

Class chart and sample implementation:

In the decoration mode, the roles are:

Abstract component role: provides an abstract interface to standardize the objects that are prepared to receive additional responsibilities.

Concrete component role: defines a class that will receive additional responsibilities.

Decorator: holds an instance of a component object and defines an interface consistent with the abstract Component Interface.

Concrete decorator: attaches "additional responsibilities to the component object.

[CPP]View plaincopy
  1. # Include <string>
  2. # Include <iostream>
  3. # Include <memory>
  4. Using namespace STD;
  5. // Abstract class Tank
  6. Class Tank
  7. {
  8. Public:
  9. Virtual void shot () = 0;
  10. Virtual void run () = 0;
  11. Public:
  12. Virtual ~ Tank ()
  13. {
  14. Cout <"in the destructor of Tank" <Endl;
  15. }
  16. };
  17. // Specific class T50
  18. Class T50: Public Tank
  19. {
  20. Public:
  21. Void shot ()
  22. {
  23. Cout <"tank T50 shot ()" <Endl;
  24. }
  25. Void run ()
  26. {
  27. Cout <"tank T50 run ()" <Endl;
  28. }
  29. Public:
  30. Virtual ~ T50 ()
  31. {
  32. Cout <"in the destructor of T50" <Endl;
  33. }
  34. };
  35. // Specific class T75
  36. Class T75: Public Tank
  37. {
  38. Public:
  39. Void shot ()
  40. {
  41. Cout <"tank T75 shot ()" <Endl;
  42. }
  43. Void run ()
  44. {
  45. Cout <"tank T75 run ()" <Endl;
  46. }
  47. Public:
  48. Virtual ~ T75 ()
  49. {
  50. Cout <"in the destructor of T75" <Endl;
  51. }
  52. };
  53. // Abstract class, decorator
  54. Class decorator: Public Tank
  55. {
  56. Protected:
  57. Tank * tank;
  58. Public:
  59. Decorator (tank * tank): tank (tank) {}// decoration class of the specific tank
  60. Virtual ~ Decorator ()
  61. {
  62. Cout <"in the destructor of decorator" <Endl;
  63. }
  64. Public:
  65. Void shot ()
  66. {
  67. Tank-> shot ();
  68. }
  69. Void run ()
  70. {
  71. Tank-> Run ();
  72. }
  73. };
  74. Class infrareddecorator: Public decorator
  75. {
  76. PRIVATE:
  77. String infrared; // This is the so-called addatrried
  78. Public:
  79. Infrareddecorator (tank * tank): decorator (tank ){}
  80. Virtual ~ Infrareddecorator ()
  81. {
  82. Cout <"in the destructor of infrareddecorator" <Endl;
  83. }
  84. Public:
  85. Void set_infrared (const string & infrared)
  86. {
  87. This-> infrared = infrared;
  88. }
  89. String get_infrared () const
  90. {
  91. Return infrared;
  92. }
  93. Void run ()
  94. {
  95. Tank-> Run ();
  96. Set_infrared ("+ infrared ");
  97. Cout <get_infrared () <Endl;
  98. }
  99. Void shot ()
  100. {
  101. Tank-> shot ();
  102. }
  103. };
  104. Class amphibiandecorator: Public decorator
  105. {
  106. PRIVATE:
  107. String amphibian;
  108. Public:
  109. Amphibiandecorator (tank * tank): decorator (tank ){}
  110. ~ Amphibiandecorator ()
  111. {
  112. Cout <"in the destructor of amphibiandecorator" <Endl;
  113. }
  114. Public:
  115. Void set_amphibian (const string & hibian)
  116. {
  117. This-> amphibian = hibian;
  118. }
  119. String get_amphibian () const
  120. {
  121. Return amphibian;
  122. }
  123. Public:
  124. Void run ()
  125. {
  126. Tank-> Run ();
  127. Set_amphibian ("+ amphibian ");
  128. Cout <get_amphibian () <Endl;
  129. }
  130. Void shot ()
  131. {
  132. Tank-> shot ();
  133. }
  134. };
  135. Int main (INT argc, char ** argv)
  136. {
  137. // Adds the infrared function to the t50.
  138. Tank * tank1 (New T50 );
  139. Tank * pid1 (New infrareddecorator (tank1 ));
  140. Pid1-> shot ();
  141. Cout <Endl;
  142. Pid1-> Run ();
  143. Cout <Endl;
  144. Cout <Endl <"---------------" <Endl;
  145. // Adds infrared and amphibious functions to T75
  146. Tank * tank2 (New T75 );
  147. Tank2-> Run ();
  148. Tank * pid2 (New infrareddecorator (tank2 ));
  149. Tank * pad2 (New amphibiandecorator (pid2 ));
  150. Pad2-> shot ();
  151. Cout <Endl;
  152. Pad2-> Run ();
  153. Cout <Endl;
  154. Cout <Endl <"--------------" <Endl;
  155. // Dynamically undo other decorations?
  156. Tank2-> Run ();
  157. Tank * tank3 (tank2 );
  158. Tank3-> Run ();
  159. Return 0;
  160. }

 

Differences between the modifier and the adapter:

1. About new responsibilities: the adapter can also add new responsibilities during the conversion, but the main purpose is not here. The decorator mode adds new responsibilities to the decorator.

2. Original interface: the adapter mode uses a new interface to call the original interface. The original interface is invisible or unavailable to the new system. The original interface is used in the decoration mode, and the system also uses the original interface for the decoration objects. (The modifier mode for adding new interfaces can be considered as its variant-"Translucent" modifier)

3. About the object of the package: the adapter knows the details of the adapter (that is, the class or the interface ). The decorator only knows what its interface is. The specific type (whether it is a base class or another derived class) is only known during running.


Key points:

1. the decorator and the decorated object have the same super type.

2. One or more decorators can wrap an object.

3. the decorator Can add his/her own actions before or after the actions of the entrusted decorator to achieve a specific purpose.

4. objects can be decorated at any time, so they can be dynamically decorated at runtime. You can use your favorite decorator to decorate objects in an unlimited number.

5. In the decoration mode, the key to inheritance is to match the type of the modifier and the decorated object, rather than obtaining its behavior.

6. the decorator is generally transparent to the customer of the component, unless the customer program depends on the specific type of the component. In actual projects, you can add new behaviors to the decorator as needed to achieve "Translucent.

Applicable scenarios and advantages and disadvantages: The decoration mode should be used in the following situations:

1. You need to extend the functions of a class or add additional responsibilities to a class.

2. You need to dynamically add functions to an object. These functions can be dynamically revoked.

3. A large number of functions are generated by the arrangement and combination of some basic functions to make the inheritance relationship unrealistic.

Advantages:

1. The purpose of the decorator mode and the inheritance relationship is to expand the object functions, but the decorator can provide more flexibility than inheritance.

2. By using different specific decorative classes and the arrangement and combination of these decorative classes, designers can create a combination of many different behaviors.

Disadvantages:

1. This is more flexible than inheritance, and it also means more complexity.

2. The decoration mode will lead to many small classes in the design. Excessive use will complicate the program.

3. The decoration mode is designed for the component type. However, if you want to program specific components, you should rethink your application architecture and whether the decorator is appropriate. Of course, you can also change the Component Interface, add new public behavior, and implement the "Translucent" modifier mode. Make the best choice in the actual project.


Related Article

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.