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

装饰模式

装饰模式也称为包装模式,是结构型设计模式之一。装饰模式是一种用于替代继承技术的一种方案。

1.定义

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

2.使用场景

(1)需要透明且动态地扩展类的功能时。且在不影响其他对象的情况下。

(2)当不能采用继承对系统进行扩展时可以使用装饰模式。比如final类。

3.UML类图

(1)Component:抽象组件。可以是一个接口或抽象类,其充当的就是被装饰的原始对象。

(2)ConcreteComponent:组件具体实现类,该类是Component类的基本实现,也是我们装饰的具体对象。

(3)Decorator:抽象装饰者,其职责就是装饰我们的组件对象,通过其子类扩展该方法以达到装饰的目的。其内部一定要有一个指向组件对象的引用。在大多数情况下,该类为抽象类,需要根据不同的装饰逻辑实现不同的具体子类。

(4)ConcreteDecoratorAConcreteDecoratorB:装饰着具体实现类。负责向构件添加新的职责。

4.简单实现

以一个男孩穿衣装扮为例。实现给男孩在家与出门的穿衣装扮。

抽象组件类(Component):

?

1

2

3

4

5

6

<code class="hljs java">public abstract class Person {

    /**

     * Person下有一个穿着的抽象方法 

     */

    public abstract void dressed();

}</code>

具体实现类(ConcreteComponent):表示要装扮的Boy

?

1

2

3

4

5

6

7

8

<code class="hljs java">public class Boy extends Person{

 

    @Override

    public void dressed() {

        System.out.println("Boy穿了内衣内裤");

    }

 

}</code>

抽象装饰类(Decorator):PersonCloth 表示人所穿着的衣服

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code class="hljs java">public class PersonCloth extends Person{

 

    protected Person mPerson; //保持一个Person类的引用

 

    public PersonCloth(Person mPerson) {

        super();

        this.mPerson = mPerson;

    }

 

    @Override

    public void dressed() {

        mPerson.dressed();

    }

}</code>

出门穿的衣服:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<code class="hljs java">public class OutsideCloth extends PersonCloth{

 

    public OutsideCloth(Person mPerson) {

        super(mPerson);

    }

 

    /**

     * 穿短袖 

     */

    private void dressShirt(){

        System.out.println("穿件短袖");

    }

 

    /**

     * 穿牛仔裤 

     */

    private void dressJean(){

        System.out.println("穿牛仔裤");

    }

 

    /**

     * 穿鞋子 

     */

    private void dressShoes(){

        System.out.println("穿鞋子 ");

    }

 

    @Override

    public void dressed() {

        super.dressed();

        dressShirt();

        dressJean();

        dressShoes();

    }

 

}</code>

在家穿的衣服:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<code class="hljs java">public class HomeCloth extends PersonCloth{

 

    public HomeCloth(Person mPerson) {

        super(mPerson);

    }

 

    /**

     * 穿短裤

     */

    private void dressShorts(){

        System.out.println("穿短裤");//在家里随便点

    }

 

    @Override

    public void dressed() {

        super.dressed();

        dressShorts();

    }

 

}</code>

装扮:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<code class="hljs cs">public class Client {

    public static void main(String[] args) {

        //首先有一个男孩

        Person person = new Boy();

 

        //在家

        PersonCloth personCloth = new HomeCloth(person);

        personCloth.dressed();

        System.out.println("--------------");

        //出门

        PersonCloth personCloth1 = new OutsideCloth(person);

        personCloth1.dressed();

 

    }

}</code>

结果

?

1

2

3

4

5

6

7

<code class="hljs asciidoc">Boy穿了内衣内裤

穿短裤

--------------

Boy穿了内衣内裤

穿件短袖

穿牛仔裤

穿鞋子 </code>

源码中的实现">5.Android源码中的实现

1.Context

Context类在Android中被称为“上帝对象”,它的本质就是一个抽象类,在装饰模式中相当于抽象组件,而在内部定义了大量的抽象方法,比如我们经常用到的startActivity方法。而真正实现是在ContextImpl中完成,那么ContextImpl 就是具体实现类。因为ContextWrapper 继承于Context ,所以ContextWrapper 就是装饰者。具体大家可以自行查看源码。

6.区别

1.与代理模式的区别

(1)装饰模式是以对客户端透明的方式扩展对象的功能,是继承方案的一个替代;而代理模式则是给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用。

(2)装饰模式应该为所装饰的对象增强功能;代理模式是对代理对象施加控制,不对对象本身功能进行增强。

2.与适配器模式的区别

适配器模式是用新接口来调用原接口,原接口对新系统是不可见的;装饰模式增强了其他对象的功能而同时又不改变它的接口。

7.总结

在实际开发中我们应该写过如下代码:其实这些新增方法的调用就类似装饰模式中的装饰者的职责,只不过这里我们没有保持对组件类的引用。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code class="hljs java">@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        //初始化数据

        initData();

 

        //初始化控件

        initViews();

 

        //初始化事件

        initEvent();

    }</code>

1.优点

(1)对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。

(2)可以通过一种动态的方式在运行时选择不同的具体装饰类,从而实现不同的行为。

(3)可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。

(4)具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。

2.缺点

(1)使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能。

(2)对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值