码迷,mamicode.com
首页 > 其他好文 > 详细

装饰模式

时间:2018-05-20 14:08:12      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:override   over   final   uml   dap   MF   兼容   ide   装饰者   

介绍

装饰模式也叫做包装模式,是结构型设计模式之一。目的是为了给一个类或对象增加行为。可以是继承的一种替代。

装饰模式也很好理解,比如一个人,给他装上火箭就能上天了,装上潜水服就能下海了,但本身还是个人,人没有任何变化。

在不使用的继承的方式下,采用装饰设计模式可以扩展一个对象的功能,可以使一个对象变得越来越强大。

定义

动态地给一个对象添加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。

使用场景

  • 需要拓展一个类的功能,增加附加职责时。
  • 需要动态增加功能,并动态删除功能时。
  • 当不能使用继承,但要提供继承的功能时。

UML图

技术分享图片

角色职责

  • Component: 抽象组件,可以是一个接口或抽象类,是被装饰的原始对象
  • ConcreteComponent:组件的具体实现类。是被装饰的具体对象。
  • Decorator: 抽象的装饰者。职责是装饰被装饰的对象。内部一定有一个对被装饰者的引用。一般情况下也是一个抽象类,根据具体逻辑实现不同的子类。如果逻辑简单可以直接是实现类。
  • ConcreteDecoratorA,B:具体的装饰者。

代码

抽象组件类:

public abstract class Component {
    public abstract void operate();
}

组件的一个具体实现类,也就是被装饰者者:

public class ConcreteComponent extends Component {
    @Override
    public void operate() {
        System.out.println("被装饰者的操作");
    }
}

抽象的装饰者,持有一个被装饰者的引用

public abstract class Decorator extends Component {
    private Component component;
    public Decorator(Component component) {
        this.component = component;
    }
    @Override
    public void operate() {
        component.operate();
    }
}

具体的两个装饰者,拓展功能:
ConcreteDecoratorA:

public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    @Override
    public void operate() {
        operateA();
        super.operate();
        operateB();
    }
    private void operateA(){
        System.out.println("装饰者A在被装饰者的操作之前加些操作");
    }
    private void operateB(){
        System.out.println("装饰者A在被装饰者的操作之前后加些操作");
    }
}

ConcreteDecoratorB:

public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }
    @Override
    public void operate() {
        operateA();
        super.operate();
        operateB();
    }
    private void operateA(){
        System.out.println("装饰者B在被装饰者的操作之前加些操作");
    }
    private void operateB(){
        System.out.println("装饰者B在被装饰者的操作之前后加些操作");
    }
}

客户端调用:

public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(component);
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(component);
        concreteDecoratorA.operate();
        concreteDecoratorB.operate();
    }
}

输出:
技术分享图片

装饰类并没有在原来的类上做审核改动,只是拓展了一些操作。通过不同的包装类就能拓展不同的功能。而传入不同的被包装类,也能拓展不同的具体对象。

在Android中的使用

我们知道RecyclerView是不支持添加addHeaderView和addFooterView功能的,但是我们在项目开发中经常还要使用到这两个功能。怎么办呢?最好的办法就是在不破坏原理结构的继承上扩展出这两个功能,所以首先考虑装模式来实现这个功能。

在实现逻辑之前先画uml图来缕清其中的关系
技术分享图片

其中MyRecyclerViewAdapter是我们实际上处理逻辑的adapter,需要添加头部和底部功能时,将其传入的WrapRecyclerAdapter中,使用WrapRecyclerAdapter添加头部和底部即可。

WrapRecyclerAdapter

/**
 * Created by hcDarren on 2017/9/30.
 * 装饰设计模式的 RecyclerView.Adapter,我们对其进行功能扩展,使它支持头部和底部的添加
 */
public class WrapRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    // 原来的RecyclerView.Adapter,并不支持头部和底部的添加
    private final RecyclerView.Adapter mRealAdapter;
    ArrayList<View> mHeaderViews;
    ArrayList<View> mFooterViews;
    /**
    *传入被装饰者
    */
    public WrapRecyclerAdapter(RecyclerView.Adapter realAdapter){
        this.mRealAdapter = realAdapter;
        mRealAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                notifyDataSetChanged();
            }
        });
        mHeaderViews = new ArrayList<>();
        mFooterViews = new ArrayList<>();
    }
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        // 问题如果想知道是哪个部分,必须要知道 position 也就是位置 ,但是目前只有 viewType
        // 头部返回 头部的ViewHolder
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return createHeaderFooterViewHolder(mHeaderViews.get(position));
        }
        // mRealAdapter 返回 mRealAdapter的ViewHolder
        final int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mRealAdapter != null) {
            adapterCount = mRealAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                // 直接传 position ,不兼容 万能适配多布局条目
                return mRealAdapter.onCreateViewHolder(parent,mRealAdapter.getItemViewType(adjPosition));
            }
        }
        // 底部返回 底部的ViewHolder
        // Footer (off-limits positions will throw an IndexOutOfBoundsException)
        return createHeaderFooterViewHolder(mFooterViews.get(adjPosition - adapterCount));
    }

    private RecyclerView.ViewHolder createHeaderFooterViewHolder(View view){
      return new RecyclerView.ViewHolder(view){};
    }

    public int getHeadersCount() {
        return mHeaderViews.size();
    }

    public int getFootersCount() {
        return mFooterViews.size();
    }

    @Override
    public int getItemViewType(int position) {
        // 把位置作为 viewType
        return position;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        // 这个方法先不写,测试一下
        // 头部和底部是都不需要做处理的,只要 mRealAdapter 要去做处理
        int numHeaders = getHeadersCount();
        if (position < numHeaders) {
            return ;
        }
        final int adjPosition = position - numHeaders;
        int adapterCount = 0;
        if (mRealAdapter != null) {
            adapterCount = mRealAdapter.getItemCount();
            if (adjPosition < adapterCount) {
                mRealAdapter.onBindViewHolder(holder,position);
            }
        }
}
    @Override
    public int getItemCount() { // 总共返回多少条 = 底部条数+头部条数+真实的Adapter条数
        return mFooterViews.size()+mHeaderViews.size()+mRealAdapter.getItemCount();
    }
    /**
     * 添加头部
     */
    public void addHeaderView(View view){
        if(!mHeaderViews.contains(view)){
            mHeaderViews.add(view);
            notifyDataSetChanged();
        }
    }
    /**
     * 添加底部
     */
    public void addFooterView(View view){
        if(!mFooterViews.contains(view)){
            mFooterViews.add(view);
            notifyDataSetChanged();
        }
    }
    /**
     * 移除头部
     */
    public void removeHeaderView(View view){
        if(mHeaderViews.contains(view)){
            mHeaderViews.remove(view);
            notifyDataSetChanged();
        }
    }
    /**
     * 移除底部
     * @param view
     */
    public void removeFooterView(View view){
        if(mFooterViews.contains(view)){
            mFooterViews.remove(view);
            notifyDataSetChanged();
        }
    }
}

装饰模式

标签:override   over   final   uml   dap   MF   兼容   ide   装饰者   

原文地址:https://www.cnblogs.com/gxl1995/p/9063166.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!