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

来源:互联网 发布:非诚勿扰网络直播时间 编辑:程序博客网 时间:2024/06/06 10:35

装饰

意图

动态给一个对象添加额外的职责,就增加功能来说,装饰(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.效率影响

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

源码下载

0 0
原创粉丝点击