Android设计模式之装饰模式

原创文章,如有转载,请注明出处:http://blog.csdn.net/myth13141314/article/details/78267978


在日常开发过程中时常需要用到设计模式,但是设计模式有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() {
        //初始化页面
    }
}
  • 上面的代码我们应该比较熟悉,这就比较类似装饰模式中装饰者的职责,就是动态地扩展了类的功能
下面我们以对在Android 设计模式之代理模式一文中的示例代码进行改造来简单应用装饰模式
首先抽象主题类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();

总结

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


欢迎关注我的公众号,和我一起每天进步一点点!
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值