Solution to C ++ Design Pattern builder Pattern

Source: Internet
Author: User

Solution to C ++ Design Pattern builder Pattern
C ++: builder Mode

Separates the construction of a complex object from its representation, so that different representations can be created during the same construction process.

 

 

I. Reasons

When constructing a window control, we usually have three initialization tasks:

UI initialization animation initialization signal slot Initialization

In this way, we can construct a window control. We can look at the following class diagram:

At first glance, there is no problem with this implementation.CenterWidgetClass is called in its constructorinitUi,initAnimation,initSlotThe three private member functions initialize the Ui, animation, and signal slot respectively. But when we start a newCenterWidgetDuring construction, the animation effect must be changed. What should I do at this time? ModifyinitAnimationMember functions? As a good programmerModify classShould Be vigilant, this design obviously violatesPrinciple of opening/closing. At this time, we encountered a problem:The constructed interfaces are fixed, and the order of construction is fixed, which requires changes in the constructed content.
Intuitively, the solution to this problem is:initUi,initAnimation,initSlotThe three member functions must be virtual functions. When an animation, Ui, or signal slot needs to change, you only need to add a new subclass and rewrite a function. However, when these three member functions become virtual functions, they cannot be called in constructors because
During the construction of a class, the vtable has not been initialized, and the virtual function mechanism does not work correctly.
So we addedInitMethod, called after the object is constructed. The class diagram is as follows:

This class diagram solves the problem of the open and closed principle, but a new problem arises, and the client needs to callInitYesInterface isolationAndSingle responsibilityWhy is this true?
The idea of the client is:

I want CenterWidgetThen CenterWidgetDisplayed

WhileCenterWidgetProvided:

Here is CenterWidgetThe instance then calls InitInterface initialization and then CenterWidgetDisplayed

For the client, it depends on an interface that it does not need.Init, ThisInitNot as required by the client, but as needed by the clientCenterWidgetAn interface forcibly matched as the logic function of the main window (Note: The interface isolation principle means that the client should not rely on interfaces that it does not need. The dependency of one class on the other class should be based on the smallest interface.). Second, as the main window classCenterWidgetAdditional responsibilities are required to manage complex constructor logic. This is not a serious problem. This solution is often effective, but we propose a more elegant solution.

II. Implementation

To solve the problem described in the previous section, we willCenterWidgetConstruct responsibility extraction from a separateBuilderClass. In this wayinitUi,initAnimation,initSlotFunction TransferBuilderClass. ByBuilderClassCenterWidgetInstance.initUi,initAnimation,initSlotThe order of the three function calls is required.DirectorClass ManagementinitUi,initAnimation,initSlotCommandBuilderThis isBuilder Mode. The builder mode and the builder ModeCenterWidgetShows the construction scheme:

Builder Mode

Use the 'centerwidget 'solution in builder Mode

Iii. Code Analysis

BelowCenterWidgetSample Code of the Solution

# Include
  
   
# Include
   
    
Using std: string; class CenterWidget {private: string Ui; string Animation; string Slot; public: virtual ~ CenterWidget () {}; void setUi (const string & x) {Ui = x;} void setAnimation (const string & x) {Animation = x ;} void setSlot (const string & x) {Slot = x;} void show () {std :: cout <"Ui =" <Ui <"Animation =" <Animation <"Slot =" <Slot <std: endl ;}}; class CenterWidgetBuilder {public: virtual ~ CenterWidgetBuilder () {} virtual void initUi () = 0; virtual void initAnimation () = 0; virtual void initSlot () = 0; virtual CenterWidget * getResult () = 0 ;}; class ConcreteCenterWidgetBuilderA: public CenterWidgetBuilder {private: CenterWidget * curWidget; public: ConcreteCenterWidgetBuilderA (): curWidget (new CenterWidget) {} virtual ~ ConcreteCenterWidgetBuilderA () {delete curWidget;}; virtual void initUi () {curWidget-> setUi ("Q Ui");} virtual void initAnimation () {curWidget-> setAnimation ("Biu ~ Biu ~ Biu ~ ");} Virtual void initSlot () {curWidget-> setSlot (" connected to your heart ");} CenterWidget * getResult () {return curWidget ;}; class ConcreteCenterWidgetBuilderB: public CenterWidgetBuilder {private: CenterWidget * curWidget; public: ConcreteCenterWidgetBuilderB (): curWidget (new CenterWidget) {} virtual ~ ConcreteCenterWidgetBuilderB () {delete curWidget;}; virtual void initUi () {curWidget-> setUi ("Q Ui");} virtual void initAnimation () {curWidget-> setAnimation ("Boom ~ Boom ~ Boom ~ ") ;}Virtual void initSlot () {curWidget-> setSlot (" connected to your heart ") ;}centerwidget * getResult () {return curWidget ;};}; class Dirctor {private: CenterWidgetBuilder * Builder; public: Dirctor (CenterWidgetBuilder * builder): Builder {}; virtual ~ Dirctor () {delete Builder;} void Construct () {Builder-> initUi (); Builder-> initAnimation (); Builder-> initSlot ();}}; int main (void) {ConcreteCenterWidgetBuilderA * builderA = new ConcreteCenterWidgetBuilderA; Dirctor * directorA = new Dirctor (builderA); directorA-> Construct (); builderA> getResult () -> show (); ConcreteCenterWidgetBuilderB * builderB = new ConcreteCenterWidgetBuilderB; Dirctor * directorB = n Ew Dirctor (builderB); directorB-> Construct (); builderB-> getResult ()-> show ();} running result: Ui = Q Ui Animation = Biu ~ Biu ~ Biu ~ Slot = connected to your heartUi = Q Ui Animation = Boom ~ Boom ~ Boom ~ Slot = connected to your heart
   
  

Duplicate and ConcreteCenterWidgetBuilderA have repeated code. To facilitate code reuse, we can use ConcreteCenterWidgetBuilderB to inherit ConcreteCenterWidgetBuilderA, and then rewrite the initAnimation to be changed. The code is modified as follows:

Class ConcreteCenterWidgetBuilderA: public CenterWidgetBuilder {protected: // change it to protected CenterWidget * curWidget for subclass access; public: ConcreteCenterWidgetBuilderA (): curWidget (new CenterWidget) {} virtual ~ ConcreteCenterWidgetBuilderA () {delete curWidget;}; virtual void initUi () {curWidget-> setUi ("Q Ui");} virtual void initAnimation () {curWidget-> setAnimation ("Biu ~ Biu ~ Biu ~ ");} Virtual void initSlot () {curWidget-> setSlot (" connected to your heart ");} CenterWidget * getResult () {return curWidget ;}; class ConcreteCenterWidgetBuilderB: public ConcreteCenterWidgetBuilderA {public: ConcreteCenterWidgetBuilderB () {} virtual ~ ConcreteCenterWidgetBuilderB () {}; // only rewrite the virtual void initAnimation () {curWidget-> setAnimation ("Boom ~ Boom ~ Boom ~ ") ;}}; Running result: Ui = Q Ui Animation = Biu ~ Biu ~ Biu ~ Slot = connected to your heartUi = Q Ui Animation = Boom ~ Boom ~ Boom ~ Slot = connected to your heart
Iv. Summary

Main advantages of the builder mode:

Decoupling the product itself from the product creation process allows different instances to be created during different creation processes to easily add new builders and create new product instances in line with the open and closed principles.

Main disadvantages of builder mode:

The builder mode can only create products with many commonalities. Similar components. If the product composition is complex and changeable, a large number of builder classes need to be defined to complicate the system.

Use Cases:

The product to be created has multiple components and the internal structure is complex. The process of creating an ordered object for the specified product must be independent of this class.

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.