`

《Head.First设计模式》的学习笔记(4)--装饰者模式

 
阅读更多

意图:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

结构

image

例子

下面我们以星巴兹(Starbuzz)的订单系统为例加以说明。

需求分析:

1)、星巴兹的饮料(Beverage)种类繁多,主要有HouseBlend、DarkRoast、Decaf、Espresso。

2)、星巴兹的调料很多,主要有Steamed Milk、Soy、Mocha、Whip。

3)、星巴兹的饮料价格是根据饮料的基础价和所加入的调料的价格相加得到。

错误设计:

根据以上的简单分析,第一种类图设计出炉:

image

其中getDescription()用来描述饮料,cost()用来计算价格。

显而易见,这个类图设计的最大缺点就是类太多,系统难以维护。所以我们需要另外的解决方案,而且新方案必须避免“类爆炸”。此时我们想到了实例变量和继承。先从Beverage基类下手,加上实例变量代表是否加上调料(Steamed Milk、Soy、Mocha、Whip等),Beverage基类的cost()计算调料的价钱,而各种具体的饮料(HouseBlend、 DarkRoast、Decaf、Espresso等)的cost()将把基础饮料的价钱和调料的价钱相加得到饮料的价钱。由此可以设计出第二种类图

image

对这个类图设计的评价:如果需求不再变化,那么这个类图设计没有错;但是需求发生了变化,这个设计就会难以招架。经过进一步的分析,我们发现部分需求被我们遗漏了。

新增加的需求:

1)、调料的价格可能发生变化。

2)、调料的种类可能发生变化。

3)、饮料的种类可能增加,不只HouseBlend、DarkRoast、Decaf、Espresso四种。

4)、顾客可能在一种饮料里加双份的同种饮料。

显然,第二种类图设计难以满足新的需求,而且对新增加的饮料而言,有可能存在不适合的调料。例如,茶子类将继承hasWhip()(加奶泡)等方法。因此,我们应该对类图设计进行改进。此时我们想到了装饰者模式,那么如何应用装饰者模式呢?

以装饰者模式构造饮料订单:

1)、以DarkRoast对象开始。image

2)、顾客想要Mocha,所以建立一个Mocha对象,并用它将DarkRoast对象包装起来。image

3)、顾客也想要Whip,所以需要建立一个Whip装饰者,并用它将Mocha对象包起来。image

4)、现在,该是为顾客算钱的时候了。通过最外圈装饰者(Whip)的cost()就可以办得到。Whip的cost()会先委托它装饰的对象(Mocha)计算出价钱,然后再加上Whip的价钱。

image

根据以上的分析,应用装饰者模式,我们可以打造一个全新的类图。

第三种类图设计(正确的类图):

image

部分代码为:

 1public class DarkRoast : Beverage
 2    {
 3        public DarkRoast()
 4        {
 5            description = "Dark Roast";
 6        }
    
 7        public override double Cost()
 8        {
 9            return 1.22;
10        }

11    }

12public class Mocha : CondimentDecorator
13    {
14        Beverage myBeverage;
15        public Mocha(Beverage paramBeverage)
16        {
17            this.myBeverage = paramBeverage;
18        }

19
20        public override string GetDescription()
21        {
22            return myBeverage.GetDescription() + ",Mocha";
23        }
 
24    
25        public override double Cost()
26        {
27            return 0.5 + myBeverage.Cost();
28        }

29    }

30class StarbuzzCoffee
31    {
32        static void Main(string[] args)
33        {
34            Beverage myBeverage = new Espresso();
35            Console.WriteLine(myBeverage.GetDescription() + " $" + myBeverage.Cost());
36
37            Beverage myBeverage2 = new DarkRoast();
38            myBeverage2 = new Mocha(myBeverage2);
39            myBeverage2 = new Mocha(myBeverage2);
40            myBeverage2 = new Whip(myBeverage2);
41            Console.WriteLine(myBeverage2.GetDescription() + " $" + myBeverage2.Cost());
42
43            Console.ReadLine();
44        }

45    }

  

 装饰模式的适用情况:

1)、需要扩展一个类的功能,或给一个类增加附加责任。

2)、需要动态地给一个对象增加功能,这些功能可以再动态地撤销。

3)、需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

使用装饰模式主要有以下的优点:

1)、装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。

2)、通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

使用装饰模式主要有以下的缺点:

由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

分享到:
评论

相关推荐

    HeadFirst 设计模式学习笔记3--装饰模式 Demo

    在“HeadFirst 设计模式学习笔记3--装饰模式 Demo”中,作者通过实例讲解了装饰模式的基本概念、结构和应用场景。这篇文章可能是从CSDN博客平台上的一个链接访问的,遗憾的是,由于我们当前无法直接访问该链接,所以...

    Head.First 设计模式学习笔记.pdf

    ### Head.First 设计模式学习笔记知识点总结 #### 一、设计模式概述 设计模式是一种用于解决软件设计中常见问题的标准化方法。通过采用设计模式,开发者可以提高代码的复用性、灵活性和可维护性。《Head First 设计...

    HeadFirst 设计模式学习笔记1--策略模式Demo

    《HeadFirst设计模式学习笔记1--策略模式Demo》 在软件工程中,设计模式是一种解决常见问题的标准方案,它提供了一种在特定情况下组织代码的模板。策略模式是设计模式中的一种行为模式,它允许在运行时选择算法或...

    HeadFirst 设计模式学习笔记2--观察者模式 demo

    总的来说,HeadFirst设计模式的学习笔记2关于观察者模式的演示,旨在帮助开发者理解如何使用观察者模式来构建可扩展的系统。通过实际的代码示例,我们可以更深入地掌握这一模式,并将其应用到日常开发中,提升代码的...

    HeadFirst设计模式学习笔记

    《HeadFirst设计模式学习笔记》是一份详尽的资料,旨在帮助读者深入理解并掌握设计模式这一编程领域的核心概念。设计模式是软件工程中的一种最佳实践,它在解决常见问题时提供了一种标准的解决方案,使得代码更易于...

    Head First设计模式读书笔记-DesignPatterns.zip

    《Head First设计模式》是一本深受开发者喜爱的设计模式学习书籍,它以易懂且生动的方式介绍了23种经典设计模式。这些模式是软件工程中经过实践验证的最佳实践,旨在提高代码的可重用性、可读性和可维护性。下面,...

    Head First 设计模式学习笔记(十四)模式的组合使用

    在《Head First 设计模式学习笔记(十四)模式的组合使用》中,作者探讨了如何在实际编程中灵活地组合多种设计模式以解决复杂问题。这篇文章可能是基于《Head First 设计模式》这本书的一个章节,该书是设计模式领域...

    读书笔记:设计模式学习笔记和代码。《图解设计模式》《Head First 设计模式》.zip

    读书笔记:设计模式学习笔记和代码。《图解设计模式》《Head First 设计模式》

    Head First 设计模式 扫描版

    《Head First 设计模式》是软件开发领域内一本广受欢迎的书籍,由Eric Freeman、Elisabeth Robson、Bert Bates和Kathy Sierra四位作者共同撰写。这本书以其独特的视觉风格和易于理解的教学方法,深入浅出地介绍了...

    Head First Servlets & JSP 学习笔记

    以上只是《Head First Servlets & JSP》一书中的部分核心知识点,实际内容还包括过滤器、监听器、MVC设计模式、JSTL等更广泛的主题,旨在帮助读者全面理解和掌握Servlet和JSP技术。通过深入学习,开发者能够构建高效...

    基于Java语言的《Head First 设计模式》学习笔记及实战练习源码

    本项目为《Head First 设计模式》的Java语言学习笔记与实战练习源码集合,包含104个文件,主要包括88个Java源文件、12个Markdown文档、3个XML配置文件及少量其他辅助文件。内容涵盖设计模式的学习笔记以及相应的代码...

    HeadFirst设计模式笔记

    《HeadFirst设计模式笔记》是深入理解软件设计思想的一份宝贵资料,主要涵盖了设计模式这一核心编程概念。设计模式是经过实践验证的解决方案模板,用于解决在软件开发中经常遇到的问题,尤其在面向对象设计中。这篇...

    Head First Design Pattern 学习笔记

    著名的《Head First Design Pattern》学习笔记,摘要这本书中的设计思路。由于书本过长,整理出笔记帮助回想起设计模式。文件是docx格式,只能由OFFICE Word 2007之后的版本打开,内附Visio类图文件。本文由个人整理...

    head first 设计模式

    通过以上对“Head First设计模式”书中可能涉及的设计模式的介绍,我们可以看出这本书是学习面向对象设计模式的绝佳资源。无论是初学者还是有一定经验的开发人员,都能从中受益匪浅。理解并熟练运用这些模式能够帮助...

    head_first_servlet&jsp学习笔记

    【Servlet&JSP基础知识】 ...以上是`head_first_servlet&jsp`学习笔记的主要知识点,涵盖了Servlet和JSP的基础、Web应用架构、MVC模式、会话管理和JSP编程等多个方面,为深入理解和实践Servlet与JSP开发奠定了基础。

    head first策略者模式

    《Head First 策略者模式》学习笔记 策略者模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们常常遇到需要根据不同的情况执行不同算法的问题。策略者模式就是为了解决这类问题而生,它...

    head first C#学习笔记:如何创建事件

    在C#编程中,事件是实现对象间通信的重要机制,特别是在设计模式中,如观察者模式。本学习笔记将深入探讨如何在C#中创建事件,以实现一个棒球模拟系统的例子。在这个系统中,我们将关注投球手、观众和裁判的交互,当...

    LotusDomino学习笔记.doc

    ### LotusDomino学习笔记知识点概览 #### 1. 选取视图的列的内容 (@Trim @DbColumn) - **@Trim**: 是一个内置的LotusScript函数,用于去除字符串两端的空白字符。 - **@DbColumn**: 此函数用于获取指定列的信息。...

Global site tag (gtag.js) - Google Analytics