Android 设计模式之装饰模式

在平常开发过程当中时常须要用到设计模式,可是设计模式有23种,如何将这些设计模式了然于胸而且能在实际开发过程当中应用得驾轻就熟呢?和我一块儿跟着《Android源码设计模式解析与实战》一书边学边应用吧!

设计模式系列文章

今天咱们要讲的是装饰模式(包装模式)


定义

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

使用场景

  • 须要透明且动态地扩展类的功能时

使用例子

  • Android源码中的ContextWrapper

实现

四大角色

  • 抽象组件:能够是抽象类或接口,是被装饰类的原始对象
  • 组件具体实现类:该类是抽象组件的具体实现,也是咱们装饰的具体对象
  • 抽象装饰者:为了装饰咱们的组件对象,其内部必定要有一个指向组件对象的引用。在大多数状况下,该类为抽象类,须要根据不一样的装饰逻辑实现不一样的子类。若是装饰逻辑单一,只有一个的状况下咱们能够省略该类直接做为具体的装饰者
  • 具体的装饰者:对抽象装饰作具体的实现

实现的要点

  • 要有具体的被装饰对象
  • 根据须要建立抽象装饰者
  • 不管是抽象装饰者仍是具体的装饰者,都会持有被装饰组件的引用
  • 具体的装饰者中确定须要有被装饰组件的方法,并根据须要加以扩展

实现方式

首先先熟悉下装饰模式的概念

public class DecoratorActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);        
        initData();        
        initView();        
    }
    
    private void initData() {
        //初始化数据
    }
    
    private void initView() {
        //初始化页面
    }
}
复制代码
  • 上面的代码咱们应该比较熟悉,这就比较相似装饰模式中装饰者的职责,就是动态地扩展了类的功能

下面咱们以对在代理模式一文中的示例代码进行改造来简单应用装饰模式

首先抽象主题类Notify类不变
public abstract class Notify {

    protected Context context;
    protected NotificationManager notificationManager;
    protected NotificationCompat.Builder builder;

    public Notify(Context context) {
        this.context = context;
        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        builder = new NotificationCompat.Builder(context);
        builder.setSmallIcon(R.drawable.ic_launcher)
                .setContentIntent(PendingIntent.getActivity(context, 0,
                        new Intent(context, NotifyActivity.class),
                        PendingIntent.FLAG_UPDATE_CURRENT));
    }

    /**
     * 发送一条通知
     */
    public abstract void send();

    /**
     * 取消一条通知
     */
    public abstract void cancel();
}
复制代码
被代理类(这里是被装饰类)NotifyNormal要稍微变更下
public class NotifyNormal extends Notify {

    public NotifyNormal(Context context) {
        super(context);
    }

    @Override
    public void send() {
        Notification notification = builder.build();
        notificationManager.notify(0, notification);
    }

    @Override
    public void cancel() {
        notificationManager.cancel(0);
    }
}
复制代码

接下来是抽象装饰者

public abstract class NotifyDecorator extends Notify {
    private Notify notify;

    public NotifyDecorator (Context context, Notify mNotify) {
        super(context);
        this.notify = mNotify;
    }

    @Override
    public void send() {
        notify.send();
    }

    @Override
    public void cancel() {
        notify.cancel();
    }
}
复制代码
  • 这里NotifyDecorator持有了被装饰组件Notify的引用,而且包含Notify的send方法和cancel方法
具体的装饰者,原来分别有NotifyNormal、NotifyBig、NotifyHeadersUp,这里对应三个具体的装饰者
  • NotifyNormalDecorator
public class NotifyNormalDecorator extends NotifyDecorator {

    public NotifyNormalDecorator (Context context, Notify notify) {
        super(context, notify);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        super.send();
    }
}
复制代码
  • NotifyBigDecorator
public class NotifyBigDecorator extends NotifyDecorator {

    public NotifyBigDecorator(Context context, Notify notify) {
        super(context, notify);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomBigContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        super.send();
    }
}
复制代码
  • NotifyHeadsUpDecorator
public class NotifyHeadsUpDecorator extends NotifyDecorator {

    public NotifyHeadsUpDecorator(Context context, Notify notify) {
        super(context, notify);
    }

    @Override
    public void send() {
        builder.setContent(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomBigContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        builder.setCustomHeadsUpContentView(new RemoteViews(context.getPackageName(), R.layout.layout_notify_normal));
        super.send();
    }
}
复制代码
以上都是在被装饰对象NotifyNormal的基础上增长或更改了通知的布局

代理类NotifyProxy也要相应的作修改

public class NotifyProxy extends Notify{
    private NotifyDecorator notifyDecorator;

    public NotifyProxy (Context context) {
        super(context);

        Notify notify = new NotifyNormal(context);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            notifyDecorator = new NotifyHeadsUpDecorator(context, notify);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            notifyDecorator = new NotifyBigDecorator(context, notify);
        } else {
            notifyDecorator = new NotifyNormalDecorator(context, notify);
        }
    }

    @Override
    public void send() {
        notifyDecorator.send();
    }

    @Override
    public void cancel() {
        notifyDecorator.cancel();
    }
}

复制代码

调用的入口依然没变

new NotifyProxy(MainActivity.this).send();
复制代码

总结

  • 从上面咱们对代理模式中的示例代码进行改造的过程咱们能够看出,装饰模式主要在于扩展了类的功能。
  • 装饰模式经过在被装饰组件的方法执行以前或以后加入新的方法来实现功能的扩展
装饰模式和代理模式的区别
  • 装饰模式是对客户端以透明的方式扩展对象的功能,是继承关系的一种替代;而代理模式则是给一个对象提供一个代理对象,并由代理对象来控制对原有对象的引用
  • 装饰模式应该为所装饰的对象增长功能,而代理对象对所代理的对象施加控制,但不对对象自己的功能进行加强

欢迎关注个人微信公众号,期待与你一块儿学习,一块儿交流,一块儿成长! bash

AntDream
相关文章
相关标签/搜索