Objective:
The grooming pattern is more flexible than generating subclasses when you want to dynamically fill in some additional responsibilities for an object (sometimes we want to add some responsibility to an object rather than the entire class)
Example:
Taking a ctextview example, we now have a text view class that provides a basic text-editing box, and when we are eager to have a text view with a scrollbar, we may derive a cscrolltextview from the Ctextview class, And when we want a text view with a border, we might derive a cbordertextview, but what if we want a text view with both a scrollbar and a border? Cscrollbordertextview? Yes, but it's not flexible.
If the demand changes now, I want to have a border, when the text is too large, it has a vertical scroll bar, when the text is too long, it has a horizontal scroll bar, when the customer wants, it can have shadows and other effects, if continue to use inheritance to meet the demand, I think it should be very painful
The grooming pattern satisfies our needs, which allows us to add some additional responsibilities to an object that is transparent to the object itself
Code:
//Abstract view classClass cview{//function definition Public://constructorsCView(void) {}//destructor~cview (void) {}//external interface Public://Draw functionVirtual void Draw(void) {}};//Abstract decoration classClass Cdecorate: Publiccview{//Variable definitionPrivate: cview* M_pview;//function definition Public://constructorscdecorate(cview* view) {M_pview = view;}//destructor~cdecorate (void) {}//external interface Public://Draw functionVirtual void Draw(void{M_pview->draw ();}};//scroll bar decoration classClass Cscrollbars: Publiccdecorate{//function definition Public://constructorsCscrollbars(cview* view):cdecorate(view) {}//destructor~cscrollbars (void) {}//intrinsic functionprotected://Draw scroll barvoid Drawscrollbars(void) {printf ("> Draw a scroll bar \ r \ n"); }//external interface Public://Draw functionVirtual void Draw(void{cdecorate::D raw (); Drawscrollbars (); }};//Border decoration classClass Cborder: Publiccdecorate{//function definition Public://constructorsCborder(cview* view):cdecorate(view) {}//destructor~cborder (void) {}//intrinsic functionprotected://Draw Bordervoid Drawborder(void) {printf ("> Draw a border \ r \ n"); }//external interface Public://Draw functionVirtual void Draw(void{cdecorate::D raw (); Drawborder (); }};//Text view classClass Ctextview: Publiccview{//Variable definitionprotected:CharM_text[max_path];//function definition Public://constructorsCtextview(Char* s) {setwindowtext (s);}//destructor~ctextview (void) {}//intrinsic functionprotected://Draw Text viewVirtual void Drawtextview(void) {printf ("> Draw a text view with text content:%s\r\n", M_text); }//external interface Public://Draw functionVirtual void Draw(void{CView::D raw (); Drawtextview (); }//Set window text voidSetWindowText (Char* s) {strcpy_s (M_text, _countof (M_text), s); }//Get window text Char* GetWindowText (void) {returnM_text; }};//Window classClass cwindows{//Variable definitionprotected: cview* m_arrwindow[10];//function definition Public://constructorscwindows(void) {ZeroMemory (M_arrwindow,sizeof(cview*) *Ten); }//destructor~cwindows (void) {ZeroMemory (M_arrwindow,sizeof(cview*) *Ten); }//external interface Public://Draw windowvoid Draw(void) { for(intNi=0; ni<Ten; ni++) {if(M_arrwindow[ni]! = NULL) M_arrwindow[ni]->draw (); } }//Add control voidAddControl (cview* pView) { for(intNi=0; ni<Ten; ni++) {if(M_arrwindow[ni] = = NULL) {M_arrwindow[ni] = PView; Break; } } }//Remove Controls voidRemovecontrol (cview* pView) { for(intNi=0; ni<Ten; ni++) {if(M_arrwindow[ni] = = PView) {M_arrwindow[ni] = NULL; Break; } } }};int_tmain (intARGC, _tchar* argv[]) {//Define a Window objectCwindows Windowsobject;//Define a plain text viewCtextview TextView ("I am a text view Control");//Add the text view as a control into the Window objectWindowsobject.addcontrol (&textview);//Make the Window object draw itselfWindowsobject.draw (); printf"----------------------------------------\ r \ n");//Remove the text view from the Window objectWindowsobject.removecontrol (&textview);//---------------------------// ///Now add a scroll bar to this text viewcscrollbars* Pscrollbars =NewCscrollbars (&textview);//Add "text view with scroll bar" to Window objectWindowsobject.addcontrol (Pscrollbars);//Make the Window object draw itselfWindowsobject.draw (); printf"----------------------------------------\ r \ n");//Remove "text view with scroll bar" from Window objectWindowsobject.removecontrol (Pscrollbars); Delete Pscrollbars;//---------------------------// ///Now add a border to this text viewcborder* Pborderobject =NewCborder (&textview);//Add "text View with borders" to the Window objectWindowsobject.addcontrol (Pborderobject);//Make the Window object draw itselfWindowsobject.draw (); printf"----------------------------------------\ r \ n");//Remove the "text view with borders" from the Window objectWindowsobject.removecontrol (Pborderobject); Delete Pborderobject;//---------------------------// ///Now add a border to this text view, plus a scroll barcborder* Pborderscrollbars =NewCborder (NewCscrollbars (&textview));//Add "text view with both border and scroll bar" to the Window objectWindowsobject.addcontrol (Pborderscrollbars);//Make the Window object draw itselfWindowsobject.draw (); printf"----------------------------------------\ r \ n");//Remove "text view with both border and scroll bar" from Window objectWindowsobject.removecontrol (Pborderscrollbars); Delete Pborderobject;//---------------------------//GetChar ();return 0;}
Summarize:
The advantage of the retouching mode is that you can add or remove some extra responsibilities for an object at run time, anywhere, and the object itself is unaware of it.
Decorate (modified mode)