Java结构型设计模式-装饰(二)

装饰

意图

动态给一个对象添加额外的职责,就增加功能来说,装饰(Decorator)模式优于继承。装饰属于对象适配器模式的一种。

别名

包装器Wrapper

动机

当我们希望给某个对象而不是整个类添加功能时,例如,一个图形用户界面工具箱允许你对任何一个用户界面组件增加特性,例如为TextView增加边框。
使用继承机制是添加功能的有效途径,子类可以持续拥有边框的特性。但这种方法不够灵活,用户不能控制对组件加框的方式和时机。
一种较为灵活的方式就是将对象嵌入另一个对象中,由这个对象添加边框,我们称这个嵌入的对象为装饰

适用性

在以下情景可以使用装饰模式

在不影响其他对象的情况下。
当不便于采用生成子类进行扩充的情形,例如父类的子类已经非常多了,从程序设计的角度不便于扩充。

参与者

这里写图片描述

Component
  • 定义一个对象接口,可以给这些对象动态增加职责。
ConcreteComponent
  • 定义一个对象,可以给对象增加职责
Decorator
  • 抽象装饰者,继承Component接口,从外类来狂战Componet功能
ConcreteDecorator
  • 实现抽象装饰着,向ConcreteComponent对象增加职责,一般构造方法接受ConcreteComponent对象。

实现

例如我们的充电器,有些充电器就降压后的5V电压充电,有些充电器带有过流保护的功能。那么我们假设不带过流保护功能的为ConcreteComponent,带过流保护的为ConcreteDecorator。

Component

public interface Component
{
    public void Voltage5V();
}

ConcreteConponent

public class ConcreteComponent implements Component
{
    @Override
    public void Voltage5V ()
    {
        System.out.println("输出5V电压");
    }
}

Decorator

public abstract class Decorator extends ConcreteComponent
{
    private ConcreteComponent mConcreteComponent;

    public Decorator ( ConcreteComponent concreteComponent )
    {
        mConcreteComponent = concreteComponent;
    }

    protected abstract void addProtect ();

}

ConcreteDecorator

public class ConcreteDecorator extends Decorator
{

    public ConcreteDecorator ( ConcreteComponent concreteComponent )
    {
        super(concreteComponent);
    }

    @Override
    protected void addProtect ()
    {
        super.Voltage5V();
        System.out.println("增加过流保护\n");
    }


}

Test

public class Test
{

    public static void main(String[] args)
    {
        ConcreteComponent component = new ConcreteComponent();
        ConcreteDecorator decorator = new ConcreteDecorator(component);
        decorator.addProtect();     //out add protect.

        component.Voltage5V();      //out not protect.

    }

}

协作

1.得到ConcreteComponet的对象,然后将对象赋入ConcreteDecorator构造器创建对象。
2.ConcreteDecorator对象附加职责。

Android中的Decorator

当我们使用RecyclerView的时候,你可能希望你的RecyclerView有以下功能添加提示无数据的空界面、添加顶部和底部的View、添加下拉监听事件,而因为界面的不同只是需要其中1~3项的功能。这时候装饰模式便派上用场了。下面进行解析。
注:Java类库中的java.io.InputStream、OutputStream、Reader、Writer这些类的所有子类,它们都有一个接受相同类型作为参数的构造函数,返回增加额外方法的子类。
RecyclerView.Adapter相当于Decorator的共同抽象接口。

RecyclerView.Adapter

 public static abstract class Adapter<VH extends ViewHolder> 
 {
       ......
 }
EmptyWrapper相当ConcreteDecorator,Decorator的构造器都是同样接受共同抽象接口的实例。

EmptyWrapper

public class EmptyWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
    public static final int ITEM_TYPE_EMPTY = Integer.MAX_VALUE - 1;

    private RecyclerView.Adapter mInnerAdapter;
    private View mEmptyView;
    private int mEmptyLayoutId;

    /**
     * Receive same abstract class as parameter. 
     * @param adapter RecyclerView.Adapter
     */
    public EmptyWrapper(RecyclerView.Adapter adapter)
    {
        mInnerAdapter = adapter;
    }
    /**
     * Add function.
     */
    private boolean isEmpty()
    {
        return (mEmptyView != null || mEmptyLayoutId != 0) && mInnerAdapter.getItemCount() == 0;
    }

    /**
     * Add function.
     * @param emptyView view
     */  
    public void setEmptyView(View emptyView)
    {
        mEmptyView = emptyView;
    }

    /**
     * Add function.
     * @param layoutId id
     */
    public void setEmptyView(int layoutId)
    {
        mEmptyLayoutId = layoutId;
    }
    .....
}
同理

HeaderAndFooterWrapper

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;
    }
     /**
     * add header's View.
     * @param view
     */
    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);
    }
    .......

Test

private void initRecycleView ()
{
        mAdapter = new CommonAdapter< Scenery.ResultBean >(getActivity(), R.layout.item_scenery, mDatas)
        {
            @Override
            protected void convert ( ViewHolder holder, Scenery.ResultBean info, int position )
            {
                ImageLoader.loadURLImage(getActivity(), info.imgurl, holder.getView(R.id.view_iv_scenery));
                holder.setText(R.id.title_tv_scenery, info.title);
            }
        };

        mEmptyWrapper = new EmptyWrapper< Scenery.ResultBean >(mAdapter);
        mEmptyWrapper.setEmptyView(LayoutInflater.from(mContext).inflate(R.layout.view_empty, mRecyclerView, false));

        mRecyclerView.setAdapter(mEmptyWrapper);
}

效果

1.比静态继承更为灵活

与对象的继承相比,Decorator模式提供了更加灵活向对象添加功能的方式,减少了类的复杂程度。

2.避免在层次结构高层的类有太多特征

Decorator模式提供了一种“即用即付”的方式来添加功能,你在设计之前可以不用过多的预见功能,可以使用Decorator逐渐添加功能。遵循了设计的“开闭原则”

3.不可随意更改Component

因为所有的Decorator都继承了共同的抽象接口Component,如果Component发生变化,会影响所有的Decorator。

4.调试困难

比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐,所以只在必要的时候使用装饰者模式。

5.效率影响

装饰链不能过长,否则会影响效率。

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值