装饰模式

Posted dsliang12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰模式相关的知识,希望对你有一定的参考价值。

android 设计模式之装饰模式

本系列是针对Android的一系列设计模式文章


    一般来说当我们想扩展一个类的某一个功能的时候我们会立马想到面向对象的继承.
    我们可以理解继承是给整个类添加新的功能.但是如果我们需要给某一个类的实例添加一个功能的时候继承的方式就显得不是那么从容了.这个时候就是装饰模式大展拳脚的场景了.

    TextView是我们日常开发中经常使用到的.假设现在有需求要给TextView添加边框.我们可以选择继承TextView的方式并且在onDraw函数里面调用super.onDraw以后绘制一层边框,从而完成任务.假设现在又有新需求要给TextView添加滚动条.那么我们继续继承TextView并且和之前的方式一样完成任务.

class ScrollTextView extends TextView

...

protected void onDraw (Canvas canvas)
    super.onDraw(canvas);
    drawScroll();


void drawScroll()
    ...

...

    但是领导突然说我们现在的新需求是需要TextView既有滚动条又要又边框.这样一来之前的工作都白费了么?如果采用继承的方式就会出现这样的尴尬.

    那么现在看看怎么用装饰模式解决这个问题.

    添加滚动条职责.添加ScrollDecorator类并且是继承TextView但是我们在构造函数的里面传递一个TextView.ScrollDecorator里面持有一个TextView实例,并且在内部实现一个绘制边框的功能函数.

class ScrollDecorator extends TextView

...

TextView mTextView;

public ScrollDecorator (TextView textView)
    mTextView = textView;


protected void onDraw (Canvas canvas)
    super.onDraw(canvas);
    drawScroll();


void drawScroll()
    ...

...

    装饰模式的重点就在于装饰类持有被装饰类的一个实例,并且继承自被装饰类.然后对于接受到的消息都转发给持有的被装饰类的实例.在外部起来ScrollDecorator和TextView并没有区别.ScrollDecorator想一层装饰一样覆盖在TextView身上.

    当然BorderDecorator的实现也是同理

class BorderDecorator extends TextView

...

TextView mTextView;

public ScrollDecorator (TextView textView)
    mTextView = textView;


protected void onDraw (Canvas canvas)
    super.onDraw(canvas);
    drawScroll();


void drawScroll()
    ...

...

    当我们需要给TextView添加滚动条和边框的时候只需简单的叠加就可以了.无需再次实现新的类.这是继续的方式没办法实现的.

TextView textView = new TextView(...);
//添加滚动条
textView = new ScrollDecorator(textView);
//添加边框
textView = new BorderDecorator(textView);

    装饰模式最大的优势在于附加功能可以简单的组合实现各种复杂的效果.优势在组合!


    在使用RecycleView的时候底部加载更多就是可以使用装饰模式实现.

    实现一个简单的Adapter

package com.dsliang.androiddesignpatterns.decorator;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.dsliang.androiddesignpatterns.R;
import com.dsliang.androiddesignpatterns.ViewHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by dsliang on 2016/9/18.
 */
public class SimpleRecycleViewAdapter extends RecyclerView.Adapter<ViewHolder> 

    Context mContext;
    List<String> mList;

    LayoutInflater mLayoutInflater;

    public SimpleRecycleViewAdapter(Context context, List<String> list) 

        if (null == context)
            throw new IllegalArgumentException("Parameter is null");

        mContext = context;
        mList = null != list ? list : new ArrayList<String>();

        mLayoutInflater = LayoutInflater.from(context);
    


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View view;

        view = mLayoutInflater.inflate(R.layout.layout_simple_recycleview_item, parent, false);

        return new ViewHolder(mContext, view);
    

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) 
        holder.setText(R.id.txtTag, mList.get(position));
    

    @Override
    public int getItemCount() 
        return mList.size();
    


BottomLoadDecorator底部加载更多装饰器

package com.dsliang.androiddesignpatterns.decorator;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;

import com.dsliang.androiddesignpatterns.ViewHolder;

/**
 * Created by dsliang on 2016/9/18.
 */
public class BottomLoadDecorator extends RecyclerView.Adapter<ViewHolder> 

    static final private int BOTTOM_LOAD_ITEM_TYPE = Integer.MAX_VALUE - 1;

    RecyclerView.Adapter mAdapter;
    Context mContext;
    LayoutInflater mLayoutInflater;

    int mLayoutId;

    public BottomLoadDecorator(Context context, RecyclerView.Adapter adapte, int layoutId) 
        if (null == adapte || null == context)
            throw new IllegalArgumentException("Parameter is null");

        if (0 == layoutId)
            throw new IllegalArgumentException("Parameters can not be zero");

        mContext = context;
        mAdapter = adapte;
        mLayoutId = layoutId;

        mLayoutInflater = LayoutInflater.from(context);
    


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

        ViewHolder viewHolder = null;

        if (BOTTOM_LOAD_ITEM_TYPE == viewType) 
            viewHolder = new ViewHolder(mContext, mLayoutInflater.inflate(mLayoutId, parent, false));
         else 
            viewHolder = (ViewHolder) mAdapter.onCreateViewHolder(parent, viewType);
        

        return viewHolder;
    

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) 
        if (isBottomLoadView(position)) 
            //do something
         else 
            mAdapter.onBindViewHolder(holder, position);
        
    

    boolean isBottomLoadView(int position) 
        return position >= mAdapter.getItemCount();
    

    @Override
    public int getItemCount() 
        return mAdapter.getItemCount() + 1;
    

    @Override
    public int getItemViewType(int position) 
        return isBottomLoadView(position) ? BOTTOM_LOAD_ITEM_TYPE : mAdapter.getItemViewType(position);
    

Activity代码

package com.dsliang.androiddesignpatterns.decorator;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.dsliang.androiddesignpatterns.R;

import java.util.Arrays;
import java.util.List;

/**
 * Created by dsliang on 2016/9/18.
 */
public class DecoratorActivity extends AppCompatActivity 

    RecyclerView mRecyclerView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_decorator);

        initView();
        initDate();
    

    private void initDate() 

        RecyclerView.Adapter adapter;
        List<String> list;

        list = Arrays.asList(getResources().getStringArray(R.array.english_letters));
        adapter = new SimpleRecycleViewAdapter(this, list);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        adapter = new BottomLoadDecorator(this, adapter, R.layout.layout_bottom_load_decorator);
        mRecyclerView.setAdapter(adapter);
    

    private void initView() 
        mRecyclerView = (RecyclerView) findViewById(R.id.recycleViewDecorator);
    

添加底部加载更多简单加一行代码就完成了

adapter = new BottomLoadDecorator(this, adapter, R.layout.layout_bottom_load_decorator);

    当然顶部刷新也是同理可以实现的,并且可以和BottomLoadDecorator组合在一起使用.每一个功能以装饰类的形式出现并且能够自由自由.


效果图


设计模式Demo
https://github.com/dsliang/AndroidDesignPatterns

以上是关于装饰模式的主要内容,如果未能解决你的问题,请参考以下文章

全球首个5G产品认证花落华为,远程视讯将助企业大展拳脚

Python练习

电赛来袭

python小练习

基于QtQuick的QCustomPlot实现

WPF点滴 行为-Behavior