Decorator mode and its application
tags (space delimited): Design Patterns in Java and Android applications
A few days ago to see the great God's Android elegant for Recyclerview add Headerview and Footerview, find decorator mode in some cases is designed so elegant, now summarized as follows:
This blog mainly explains a few questions
- What is decorator mode
- How to implement Decorator mode
- The pros and cons of decorator mode
- The application of Decorator mode in Android
For the observer design pattern, you can refer to my blog Observer design mode Vs event delegate (Java)
Reprint please indicate the original blog address: http://blog.csdn.net/gdutxiaoxu/article/details/51885105
Demo:https://github.com/gdutxiaoxu/sample_baserecycleradapter.git
What is a decorator mode application scenario
Coffee shops can add different ingredients-mocha, milk, sugar, milk bubbles, different drinks and different ingredients have different prices, how to achieve it?
Perhaps your first impressions would have thought of using inheritance,
1. First define a coffee base class
2. For the addition of sugar, milk, Gamoca, add milk bubbles, respectively, write a subclass inheritance
3. For adding sugar, and adding milk to write a class, for the addition of sugar, and Mocha write a class, for the addition of sugar, and milk bubble write a class, for adding sugar, plus milk, mocha to write a class-
in this case, you will find that there are four kinds of ingredients to write more than 10 kinds of implementation classes, if our ingredients are more than 20 or more than 30, then the use of inheritance this way will definitely make our sub-class explosion, how to solve you, the answer is to use decorator mode
Defined
I think decorator mode is a way of dynamically adding more versatility on top of existing functionality, which decorates the core responsibilities or main behaviors of the original class.
Class UML diagram
How to implement the decorator mode? First, let's take a look at our design class diagram.
- 1) First we define a COFFCE base class
/** * @ explain: Here coffee equivalent to our component, * is to decorate the class * * @ Author:xujun on 2016/7/10 23:16 * @ email:[email protected] */ public abstract class coffee { /** * *< Span class= "Hljs-javadoctag" > @return return price */ public abstract int getprice (); /** * return name * @return */ public abstract String getname ();}
- 2) Next we define a decorator class that inherits our Coffice base class
/** * @ explain: * @ author:xujun on 2016/7/10 23:21 * @ email:[email protected] */publicabstractclass Decorator extends Coffee{ protected Coffee mCoffee; /** * 通过组合的方式把Coffee对象传递进来 * @param coffee */ publicDecorator(Coffee coffee){ mCoffee=coffee; }}
- 3) Next, let's see how our subclasses are implemented.
Public class milkdecorator extends Decorator { /** * Pass the Coffee object in a combined way * * @param Coffee */ Public Milkdecorator(Coffee Coffee) {Super(coffee); }@Override Public int GetPrice() {returnMcoffee.getprice () +Ten; }@Override PublicStringGetName() {return "Addmilk"; }}
In fact, the core code on the following line, at the original price plus the price of milk added
return mCoffee.getPrice()+10
- 4) Next it is not difficult to imagine adding sugar, on the milk bubble. As for the operation of the Mocha, the price of the ingredients is added above the original
return mCoffee.getPrice()+2;return mCoffee.getPrice()+15;return mCoffee.getPrice()+20;
Summarize
After you want to calculate the sugar, on the milk, and the price of the milk bubble coffee, just need this
newnewnewnew MilkFoamDecorator(mCoffee);int price1 = mCoffee.getPrice();System.out.println("price1="+price1);
After you want to calculate the sugar, the price of the milk coffee, only need this
newnewnew MilkDecorator(mCoffee);int price1 = mCoffee.getPrice();System.out.println("price1="+price1);
Advantages and disadvantages of decorator mode
- Removing the adornment function from a class can simplify the original class
- The core functions of the class can be distinguished from the decorative functions, the structure is clear and the repetitive decorative logic of the related classes can be removed.
The application of Decorator mode in Android
As already mentioned, the reason for learning decorator design patterns is that because of seeing the blog of the Great God of Recyclerview Android Elegant add Headerview and Footerview to the
- Let's take a look at how we elegantly add Headerview and Footerview to Recyclerview
/** * Blog address: Http://blog.csdn.net/gdutxiaoxu * @author Xujun * @time 2016/7/7 17:29. * * Public class headerandfooterwrapper<T> extends recyclerview. Adapter<recyclerview. Viewholder> { Private Static Final intBase_item_type_header =100000;Private Static Final intBase_item_type_footer =200000;PrivateSparsearraycompat<view> mheaderviews =NewSparsearraycompat<> ();PrivateSparsearraycompat<view> mfootviews =NewSparsearraycompat<> ();PrivateRecyclerview.adapter Minneradapter; Public Headerandfooterwrapper(Recyclerview.adapter Adapter) {Minneradapter = adapter; }@Override PublicRecyclerview.viewholderOncreateviewholder(ViewGroup parent,intViewType) {if(Mheaderviews.get (viewtype)! =NULL) {Viewholder holder = Viewholder.createviewholder (Parent.getcontext (), Mheaderviews.get (v Iewtype));returnHolder }Else if(Mfootviews.get (viewtype)! =NULL) {Viewholder holder = Viewholder.createviewholder (Parent.getcontext (), Mfootviews.get (Vie Wtype));returnHolder }returnMinneradapter.oncreateviewholder (parent, ViewType); }@Override Public int Getitemviewtype(intPosition) {if(Isheaderviewpos (position)) {returnMheaderviews.keyat (position); }Else if(Isfooterviewpos (position)) {returnMfootviews.keyat (Position-getheaderscount ()-getrealitemcount ()); }returnMinneradapter.getitemviewtype (Position-getheaderscount ()); }Private int Getrealitemcount() {returnMinneradapter.getitemcount (); }@Override Public void Onbindviewholder(Recyclerview.viewholder holder,intPosition) {if(Isheaderviewpos (position)) {return; }if(Isfooterviewpos (position)) {return; } minneradapter.onbindviewholder (Holder, Position-getheaderscount ()); }@Override Public int GetItemCount() {returnGetheaderscount () + getfooterscount () + Getrealitemcount (); }@Override Public void Onattachedtorecyclerview(Recyclerview Recyclerview) {Wrapperutils.onattachedtorecyclerview (Minneradapter, Recyclerview,NewWrapperutils. Spansizecallback () {@Override Public int getspansize(Gridlayoutmanager LayoutManager, Gridlayoutmanager. Spansizelookup Oldlookup,intPosition) {intViewType = Getitemviewtype (position);if(Mheaderviews.get (viewtype)! =NULL) {returnLayoutmanager.getspancount (); }Else if(Mfootviews.get (viewtype)! =NULL) {returnLayoutmanager.getspancount (); }if(Oldlookup! =NULL)returnOldlookup.getspansize (position);return 1; } }); }@Override Public void Onviewattachedtowindow(Recyclerview.viewholder Holder) {Minneradapter.onviewattachedtowindow (holder);intPosition = Holder.getlayoutposition ();if(Isheaderviewpos (position) | | Isfooterviewpos (POSITION)) {Wrapperutils.setfullspan (holder); } }Private Boolean Isheaderviewpos(intPosition) {returnPosition < Getheaderscount (); }Private Boolean Isfooterviewpos(intPosition) {returnPosition >= Getheaderscount () + Getrealitemcount (); } Public void Addheaderview(View view) {Mheaderviews.put (mheaderviews.size () + base_item_type_header, view); } Public void Addfootview(View view) {Mfootviews.put (mfootviews.size () + base_item_type_footer, view); } Public int Getheaderscount() {returnMheaderviews.size (); } Public int Getfooterscount() {returnMfootviews.size (); }}
- Then let's take a look at how we use it.
Madapter =NewSinglepersonadapter ( This, Mdatas, r.layout.main_chat_from_msg); mheaderandfooterwrapper=NewHeaderandfooterwrapper (Madapter); TextView T1 =NewTextView ( This); T1.setpadding (Ten,Ten,Ten,Ten); T1.setbackgroundcolor (Color.gray); T1.settext ("Header 1"); TextView t2 =NewTextView ( This); T2.settext ("Header 2"); T2.setpadding (Ten,Ten,Ten,Ten); T2.setbackgroundcolor (Color.gray); Mheaderandfooterwrapper.addheaderview (t1); Mheaderandfooterwrapper.addheaderview (T2); Mrecyclerview.setadapter (Mheaderandfooterwrapper);
is not very simple, just a few lines of code, you can add headerview or foot on the basis of the original adapter and view, specific code analysis please see the blog Android Elegant add Headerview and Footerview for Recyclerview
Reference article Android elegant for Recyclerview add Headerview and Footerview
For the observer design pattern, you can refer to my blog Observer design mode Vs event delegate (Java)
Reprint please indicate the original blog address: http://blog.csdn.net/gdutxiaoxu/article/details/51885105
Demo:https://github.com/gdutxiaoxu/sample_baserecycleradapter.git
Decorator mode and its application