《Android源码设计模式解析与实战》读书笔记(二十一)——装饰者模式

在之前的我为 RecyclerView 添加 HeaderView 和 FooterView 的时候就提到了 ListView 在添加头布局和脚布局时就用到了装饰者模式,装饰者模式又称为包装模式(Wrapper Pattern),它使用一个对客户端透明的方式来动态扩展对象的功能,同时也是替代继承关系的方案之一。在生活中也能体现装饰者模式,比如人要穿衣服,可以穿运动装和正装,但是无论怎么样,本质都还是一个人,只是装饰了不同的衣着。所以装饰者模式就是装饰物不同,但是本质不变。


第二十一章 装饰模式

1.定义

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


2.使用场景

1).需要透明且动态地扩展类的功能时。


3.简单实现

装饰模式一般有四类角色:
Component :抽象组件,一般为接口或者抽象类,充当被装饰的原始对象。
ConcreteComponent :具体组件,具体的被装饰对象。
Decorator :抽象装饰者,一般为抽象类,内部有一个指向组件的引用,根据不同的装饰逻辑实现不同的具体子类,如果具体装饰者只有一个的话,可以省略此类。
ConcreteDecorator :具体装饰者,对抽象装饰者作出具体实现。

就拿开头提到了例子来说,人的衣着可能会随时变化,一个男生,在家穿得可能比较随便,但是出去运动或者约会时,就会装饰不同的穿着,我们就可以用装饰模式来实现,而不用创建多个男生子类,比如运动型男生和约会型男生了。

Person(抽象组件)类:

public abstract class AbstractPerson {
    public abstract void dressed();
}

Boy(具体组件)类:

public class Boy extends AbstractPerson {
    private AbstractDressing mAbstractDressing;

    @Override
    public void dressed() {
        System.out.println("男生夏天在家一般只穿条内裤");
    }

    public void sport() {
        if (mAbstractDressing == null || !(mAbstractDressing instanceof SportDressing)) {
            mAbstractDressing = new SportDressing(this);
            mAbstractDressing.dressed();
        }
    }
    public void date(){
        if (mAbstractDressing == null || !(mAbstractDressing instanceof DateDressing)) {
            mAbstractDressing = new DateDressing(this);
            mAbstractDressing.dressed();
        }
    }
}

AbstractDressing(抽象装饰者):

public abstract class AbstractDressing extends AbstractPerson {
    private AbstractPerson mAbstractPerson;

    public AbstractDressing(AbstractPerson mAbstractPerson) {
        this.mAbstractPerson = mAbstractPerson;
    }

    @Override
    public void dressed() {
        mAbstractPerson.dressed();
    }
}

SportDressing(具体装饰者):

public class SportDressing extends AbstractDressing {
    public SportDressing(AbstractPerson mAbstractPerson) {
        super(mAbstractPerson);
    }

    private void sportsVest() {
        System.out.println("穿上运动背心");
    }

    private void sportShorts() {
        System.out.println("穿上运动短裤");
    }

    private void sportShoes() {
        System.out.println("穿上运动鞋");
    }

    @Override
    public void dressed() {
        super.dressed();
        sportsVest();
        sportShorts();
        sportShoes();
    }
}


DateDressing(具体装饰者):

public class DateDressing extends AbstractDressing {
    public DateDressing(AbstractPerson mAbstractPerson) {
        super(mAbstractPerson);
    }

    private void shirts() {
        System.out.println("穿上衬衣");
    }

    private void trousers() {
        System.out.println("穿上西裤");
    }

    private void leatherShoes() {
        System.out.println("穿上皮鞋");
    }

    @Override
    public void dressed() {
        super.dressed();
        shirts();
        trousers();
        leatherShoes();
    }
}


客户端(MainActivity)调用:

        Boy mBoy = new Boy();
        System.out.println("在家穿的衣服");
        mBoy.dressed();
        System.out.println("运动时穿的衣服");
        mBoy.sport();
        System.out.println("约会时穿的衣服");
        mBoy.date();


运行程序,打印如下:



Boy 的本质还是那个 Boy,只是根据不同的行为而装饰了不同的东西,SportDressing 和 DateDressing 为 Boy 对象提供了功能扩展,而且是在没有直接修改原有的逻辑和结构的基础上扩展了功能。


4.总结

装饰模式与代理模式有些相似,往往会把装饰模式误以为是代理模式,它们的区别在于装饰模式是以对客户端透明的方式扩展对象的功能,是替代继承关系的方案之一,而代理模式则是给对象提供一个代理对象,由代理对象来控制对原对象的引用;装饰模式是为对象增加功能,而代理模式只是对对象施加控制,并不会对原对象的功能有所增强。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值