Xu Gong, programmer of my public account, has four years of working experience in Dachang. He replies to the dark knight and gets a copy of Android learning video. He replies to Xu Gong 666, where he can get my carefully organized resume template and lead you to Dachang.

preface

This blog will focus on a few issues

  1. What is decorator pattern
  2. How to implement decorator pattern
  3. Advantages and disadvantages of decorator pattern
  4. Decorator mode in Android

What is decorator pattern

Application scenarios

Coffee shops can add different ingredients to their coffee — mocha, milk, sugar, foam; Different drinks with different ingredients have different prices, how to achieve?

Your first thought might be to use inheritance,

  1. Start by defining a coffee base class
  2. For sugar, for milk, for mocha, for foam, we’ll subclass each
  3. For sugar, and milk write a class, for sugar, and mocha write a class, for sugar, and milk bubble write a class, for sugar, and milk, mocha write a class —-

At this point, you can see that there are more than a dozen implementation classes for four ingredients, and if we have two dozen or three dozen ingredients, then using inheritance is going to explode our subclasses, so how do you solve that, the answer is to use decorator mode

define

I think decorator pattern is a way to dynamically add more functionality to existing functionality, adding code that decorates the core responsibilities or major behaviors of existing classes.

Type of UML diagram

rendering

How do you implement the decorator pattern?

First let’s take a look at our design class diagram

    1. First we define a Coffce base class
/** * @explain: Coffee is our Component ** @author: xujun on 2016/7/10 23:16 * @email: [email protected] */
public abstract class Coffee {

    / * * * *@returnReturn price */
    public abstract int getPrice(a);

    /** * returns the name *@return* /
    public abstract String getName(a);
}

Copy the code
  • 2) Next we define a Decorator class that inherits from our Coffice base class

/** * @explain: * @author: xujun on 2016/7/10 23:21 * @email: [email protected] */
public abstract class Decorator extends Coffee{

    protected Coffee mCoffee;

    /** * Pass the Coffee object in as a composition *@param coffee
     */
    public Decorator(Coffee coffee){ mCoffee=coffee; }}Copy the code
  • 3) How is our subclass implemented
public class MilkDecorator extends Decorator {

    /** * Pass the Coffee object in as a composition **@param coffee
     */
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public int getPrice(a) {
        return mCoffee.getPrice()+10;
    }

    @Override
    public String getName(a) {
        return "addMilk"; }}Copy the code

In fact, the core code is the following line, the original price plus the price of milk

return mCoffee.getPrice()+10
Copy the code
  • 4) Next, it’s not hard to imagine adding sugar and frosting. The operation of mocha is to add the price of ingredients on the original
return mCoffee.getPrice()+2;
return mCoffee.getPrice()+15;
return mCoffee.getPrice()+20;
Copy the code

conclusion

And then if you want to calculate the price of sweetened, just milk, foam coffee, that’s all you have to do

mCoffee = new SimpleCoffee();
mCoffee = new SugarDecorator(mCoffee);
mCoffee = new MilkDecorator(mCoffee);
mCoffee = new MilkFoamDecorator(mCoffee);
int price1 = mCoffee.getPrice();
System.out.println("price1="+price1);
Copy the code

And then if you want to calculate the price of sweetened, milky coffee, that’s all you have to do

mCoffee = new SimpleCoffee();
mCoffee = new SugarDecorator(mCoffee);
mCoffee = new MilkDecorator(mCoffee);

int price1 = mCoffee.getPrice();
System.out.println("price1="+price1);
Copy the code

Advantages and disadvantages of decorator pattern

advantages

  • You can simplify the original class by removing the decoration function from the class
  • You can separate the core responsibility of a class from the decorator function, structure it clearly and remove the repetitive decorator logic of related classes.

Decorator mode in Android

rendering

As mentioned earlier, I learned decorator design mode because I saw hongyang Dashen’s blogAndroid elegant for RecyclerView add HeaderView and FooterView

  • Now let’s see how we can gracefully add HeaderView and FooterView to RecyclerView
/ * * * blog: http://blog.csdn.net/gdutxiaoxu *@author xujun
 * @time2016/7/7 17:29. * /
public class HeaderAndFooterWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final int BASE_ITEM_TYPE_HEADER = 100000;
    private static final int BASE_ITEM_TYPE_FOOTER = 200000;

    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
    private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();

    private RecyclerView.Adapter mInnerAdapter;

    public HeaderAndFooterWrapper(RecyclerView.Adapter adapter) {
        mInnerAdapter = adapter;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(mHeaderViews.get(viewType) ! =null) {
            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get
                    (viewType));
            return holder;

        } else if(mFootViews.get(viewType) ! =null) {
            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get
                    (viewType));
            return holder;
        }
        return mInnerAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderViewPos(position)) {
            return mHeaderViews.keyAt(position);
        } else if (isFooterViewPos(position)) {
            return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());
        }
        return mInnerAdapter.getItemViewType(position - getHeadersCount());
    }

    private int getRealItemCount(a) {
        return mInnerAdapter.getItemCount();
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (isHeaderViewPos(position)) {
            return;
        }
        if (isFooterViewPos(position)) {
            return;
        }
        mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());
    }

    @Override
    public int getItemCount(a) {
        return getHeadersCount() + getFootersCount() + getRealItemCount();
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils
                .SpanSizeCallback() {
            @Override
            public int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager
                    .SpanSizeLookup oldLookup, int position) {
                int viewType = getItemViewType(position);
                if(mHeaderViews.get(viewType) ! =null) {
                    return layoutManager.getSpanCount();
                } else if(mFootViews.get(viewType) ! =null) {
                    return layoutManager.getSpanCount();
                }
                if(oldLookup ! =null)
                    return oldLookup.getSpanSize(position);
                return 1; }}); }@Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        mInnerAdapter.onViewAttachedToWindow(holder);
        int position = holder.getLayoutPosition();
        if(isHeaderViewPos(position) || isFooterViewPos(position)) { WrapperUtils.setFullSpan(holder); }}private boolean isHeaderViewPos(int position) {
        return position < getHeadersCount();
    }

    private boolean isFooterViewPos(int position) {
        return position >= 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(a) {
        return mHeaderViews.size();
    }

    public int getFootersCount(a) {
        returnmFootViews.size(); }}Copy the code
  • And then how do we use it?
mAdapter = new SinglePersonAdapter(this, mDatas, R.layout.main_chat_from_msg);
mHeaderAndFooterWrapper=new HeaderAndFooterWrapper(mAdapter);

TextView t1 = new TextView(this);
t1.setPadding(10.10.10.10);
t1.setBackgroundColor(Color.GRAY);
t1.setText("Header 1");
TextView t2 = new TextView(this);
t2.setText("Header 2");
t2.setPadding(10.10.10.10);
t2.setBackgroundColor(Color.GRAY);
mHeaderAndFooterWrapper.addHeaderView(t1);
mHeaderAndFooterWrapper.addHeaderView(t2);
mRecyclerView.setAdapter(mHeaderAndFooterWrapper);

Copy the code

Is it very simple, just need a few lines of code, you can add headerView or Foot View on the basis of the original Adapter, the specific code analysis please see hongyang Dagod blogAndroid elegant for RecyclerView add HeaderView and FooterView

Refer to the articleAndroid elegant for RecyclerView add HeaderView and FooterView


Related to recommend

Android Startup Optimization (1) – Directed acyclic graph

Android startup optimization (2) – Topology sort principle and solution ideas

Android startup optimization (III) – AnchorTask open source now

Android Startup Optimization (5) – AnchorTask version 1.0.0 is now available

Android Startup Optimization (VI) – In-depth understanding of layout optimization

My 5 years of Android learning road, those years together stepped on the pit

If you feel helpful, you can follow my wechat public number programmer Xu Gong

  1. Public number programmer Xu Gong reply dark horse, get Android learning video
  2. Public number programmer Xu Gong replied xu Gong 666, get resume template, teach you how to optimize your resume, into the factory
  3. Public number programmer Xu Gong replied to the interview, you can get the interview common algorithm, sword refers to the offer question solution
  4. Public number programmer Xu Gong replies horse soldier, can obtain horse soldier study video