`

设计模式读书笔记-----装饰者模式

阅读更多
原帖地址:http://www.cnblogs.com/chenssy/archive/2013/05/23/3094138.html

        我们都知道,可以使用两种方式给一个类或者对象添加行为。


        一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。


        二是使用关联。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。


        与继承相比,关联关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象。


 


        一、基本定义                                                                                                                  


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


 


 


        二、模式结构                                                                                                                  


        装饰者模式UML结构图。



        Component: 抽象构件。是定义一个对象接口,可以给这些对象动态地添加职责。


        ConcreteComponent:具体构件。是定义了一个具体的对象,也可以给这个对象添加一些职责。


        Decorator: 抽象装饰类。是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。


        ConcreteDecorator:具体装饰类,起到给Component添加职责的功能。


 


        三、实现装饰者模式                                                                                                                                         


        情景模式:星巴兹以扩张速度快而闻名。在里面购买咖啡时,可以要求在其中加入各种调料,星巴兹会根据所加入的调料收取不同的费用,也就是说不同的咖啡与调料之间有N多不同的组合方式。每种咖啡和调料都有不同的收费。如果这个时候我们使用继承方式,则会陷入无以复加的地步。这里会有N多个类,出现“类爆炸”现象。


        结构图如下:



        装饰者模式提供了一个比较好的解决方案。



        编码实现:


        Component  Beverage.java



1 public abstract class Beverage {
2 protected String description = "Unknown Beverage";
3
4 public String getDescription() {
5 return description;
6 }
7
8 public abstract double cost();
9 }


 


        四个组件:HouseBlend.java



 1 public class HouseBlend extends Beverage {
2
3 public HouseBlend(){
4 description = "HouseBlend";
5 }
6
7 @Override
8 public double cost() {
9 return 0.89;
10 }
11
12 }


 


        DarkRoast.java



 1 public class DarkRoast extends Beverage {
2 public DarkRoast(){
3 description = "DarkRoast";
4 }
5 @Override
6 public double cost() {
7 return 1.05;
8 }
9
10 }


 


        Espresso.java



 1 public class DarkRoast extends Beverage {
2 public DarkRoast(){
3 description = "DarkRoast";
4 }
5 @Override
6 public double cost() {
7 return 1.05;
8 }
9
10 }


 


        Decat.java



 1 public class Decat extends Beverage {
2 public Decat(){
3 description = "Decat";
4 }
5
6 @Override
7 public double cost() {
8 return 0.99;
9 }
10
11 }


 


        CondimentDecorator.java



1 public abstract class CondimentDecorator extends Beverage{
2 public abstract String getDescription();
3 }


 


        Milk.java



 1 public class Milk extends CondimentDecorator {
2 Beverage beverage;
3
4 public Milk(Beverage beverage){
5 this.beverage = beverage;
6 }
7
8 @Override
9 public String getDescription() {
10 return beverage.getDescription() + " , Milk";
11 }
12
13 @Override
14 public double cost() {
15 return beverage.cost() + 0.3;
16 }
17 }


 


        Mocha.java



 1 public class Mocha extends CondimentDecorator {
2 Beverage beverage;
3 public Mocha(Beverage beverage){
4 this.beverage = beverage;
5 }
6
7 @Override
8 public String getDescription() {
9 return beverage.getDescription() + " , Mocha";
10 }
11
12 @Override
13 public double cost() {
14 return beverage.cost() + 0.20;
15 }
16
17 }


 


        Soy.java



 1 public class Soy extends CondimentDecorator{
2 Beverage beverage;
3 public Soy(Beverage beverage) {
4 this.beverage = beverage;
5 }
6 @Override
7 public String getDescription() {
8 return beverage.getDescription() + " , Soy";
9 }
10
11 @Override
12 public double cost() {
13 return beverage.cost() + 0.10;
14 }
15
16 }


 


        Whip.java



 1 public class Whip extends CondimentDecorator {
2 Beverage beverage;
3 public Whip(Beverage beverage){
4 this.beverage = beverage;
5 }
6 @Override
7 public String getDescription() {
8 return beverage.getDescription() + " , Whip";
9 }
10
11 @Override
12 public double cost() {
13 return beverage.cost() + 0.20;
14 }
15
16 }


 


        测试程序



 1 public class StarbuzzCoffee {
2
3 /**
4 * @param args
5 */
6 public static void main(String[] args) {
7 Beverage beverage = new Espresso();
8 System.out.println(beverage.getDescription() + " $" + beverage.cost());
9
10 Beverage beverage2 = new DarkRoast();
11 beverage2 = new Mocha(beverage2);
12 beverage2 = new Mocha(beverage2);
13 beverage2 = new Whip(beverage2);
14 System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
15 }
16
17 }


 


        运行结果



        四、装饰者模式的优缺点                                                                                                


        优点


           1、装饰者模式可以提供比继承更多的灵活性


           2、可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。


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


           4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。


 


        缺点


           1、会产生很多的小对象,增加了系统的复杂性


           2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。


 


        、装饰者模式的适用场景                                                                                           


                 1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。


                 2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。  当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。


 


        六、总结                                                                                                                       


                 1、 组合和委托可以在运行时动态的添加新的行为,而继承是静态的,在系统编译时就已经决定了对象的行为。


                 2、装饰者模式意味着一群装饰者类,这些类用来包装具体组件


                 3、装饰者可以在被装饰者的行为前面或者后面加上自己的行为,甚至可以将被装饰者的行为整个取代掉,从而达到特定的目的。


                 4、可以用多个装饰者包装一个组件。


                 5、装饰者一般对于组件的客户是透明的,除非客户程序依赖于组件的具体类型。


                 6、装饰者会导致设计中出现许多的小对象,如果过度的使用,会让系统变得更加复杂。


                 7、装饰者和被装饰者对象有相同的超类型。


 

本文链接

分享到:
评论

相关推荐

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

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

    设计模式读书笔记

    创建型设计模式关注的是对象的创建,如工厂方法、抽象工厂、建造者、原型和单例模式,它们分别处理不同程度的对象创建延迟和实例化过程。结构型模式则涉及如何组合类和对象,包括适配器、桥接、组合、装饰器、外观、...

    设计模式Golang实现《研磨设计模式》读书笔记.zip

    设计模式Golang实现《研磨设计模式》读书笔记Go语言设计模式Go语言设计模式的实例代码创建模式工厂简单模式(Simple Factory)工厂方法模式(工厂方法)抽象工厂模式(Abstract Factory)创建者模式(Builder)原型...

    设计模式的读书总结笔记

    这篇“设计模式的读书总结笔记”是对设计模式深入理解和应用的结晶,包含对各种模式的实例解析、优缺点分析以及如何在实际项目中应用的指导。 一、设计模式的基本概念 设计模式并不直接提供代码实现,而是描述在...

    JAVA与模式读书笔记。

    在《JAVA与模式读书笔记》中,我们探讨的是Java编程语言与设计模式的结合应用,这对于深入理解面向对象编程和提升软件开发能力至关重要。设计模式是软件工程中的最佳实践,它们是解决常见问题的模板,可以提高代码的...

    javaIO读书笔记

    IO系统解构有装饰者设计模式息息相关,所以先从分析它们的关系:

    java源码解读-DesignPattern:Android源码设计模式解析与实战读书笔记源代码

    Android源码设计模式解析与实战读书笔记源代码 说明: 包名factorypattern.normal表示的是工厂方法模式的普通用法 包名factorypattern.practices表示的是工厂方法模式的常用 包名observerpattern表示的是观察者模式...

    Go语言实战读书笔记系列合集.zip

    - **Go语言设计模式**:如工厂模式、单例模式、装饰器模式等在Go语言中的实现。 - **Go语言性能调优**:如何利用工具分析和优化Go程序的性能。 - **Go语言的最佳实践**:如何编写符合Go语言风格的代码,遵循Go语言的...

    GoF23种经典模式+简单工厂模式讲解还有一篇心得

    刘晓军的设计模式读书笔记汇总可能涵盖了对这些模式的深入理解和应用示例,帮助读者更好地掌握如何在实际项目中运用这些模式。整体心得文档可能会提供作者在学习过程中对设计模式的整体理解和感悟,包括哪些模式在何...

    《把你的英文用起来》简约喜庆读书笔记ppt模板.rar

    1. **封面设计**:使用模板中的封面样式,可以包含书名《把你的英文用起来》以及个人或团队的名字,体现读书笔记的主题。 2. **目录页**:列出主要的章节或主题,方便听众快速了解笔记的结构。 3. **读后感概要**...

    Apress.Expert.Spring.MVC.and.Web.Flow.Feb.2006读书笔记

    - 在某些场景下,如使用代理或装饰者模式时,可能需要在构造完成后动态添加行为,此时使用方法注入更为灵活。 ##### 2. 各层次异常处理体系构建 - **概述**:Spring 提供了多种方式来处理不同层级的异常,包括控制...

    程序员面试宝典笔记总结

    23种设计模式是面试中常见的考点,包括单例模式、工厂模式、代理模式、装饰器模式等,理解其应用场景和实现方式。 七、框架与工具 1. **前端框架**:React、Vue、Angular的使用和原理,以及CSS预处理器如Sass、...

    《如何高效学习》读书笔记扁平风格ppt模板.rar

    这份"《如何高效学习》读书笔记扁平风格ppt模板"则是对书籍内容的精彩提炼,旨在帮助读者更好地理解和应用书中的核心概念。 扁平设计是一种简洁、直观的设计风格,它强调去除多余的装饰元素,使信息传递更为清晰。...

    clean-code-booknote:记录clean-code的读书笔记

    8. **设计模式**:书中可能会提及一些常见的设计模式,如工厂模式、观察者模式、装饰器模式等,这些模式是解决常见问题的通用解决方案,能够提升代码的灵活性和可扩展性。 9. **代码的整洁**:整洁的代码不仅意味着...

    HTML+CSS+JS我的班级网页设计期末课程大作业 web前端开发技术 web课程设计 网页规划与设计

    - **图书推荐**: 图书推荐和读书笔记。 - **婚纱摄影**: 婚纱摄影服务。 - **节日庆祝**: 庆祝节日的活动安排。 - **戒烟辅助**: 戒烟指导和支持。 - **电影评论**: 电影评论和评分。 - **摄影技巧**: 摄影...

    c++ patterns

    **二、C++模式与设计模式** 1. **工厂模式**:通过工厂函数或者工厂类来创建对象,隐藏了具体的实现细节,提高了代码的灵活性和可扩展性。 2. **单例模式**:确保一个类只有一个实例,并提供全局访问点。在C++中,...

    《流畅的Python》——读书笔记(1)

    第一部分 序幕 第1章 Python数据类型 普通方法、特殊方法 第二部分 数据结构 ...第6章 使用一等函数实现设计模式 第7章 函数装饰器和闭包 从定位参数到仅限关键字函数 函数修饰器与闭包 装饰器基础知识 装饰器何时执

    notes:JavaJava后端工程师的学习笔记https

    常用设计模式 单例模式 , 工厂模式 , 装饰者模式 , 代理模式 ... Java基础核心 JVM , 集合 , 类型 ,关键字... Java高级特性 多线程、锁、并发 框架 Spring , Mybatis , SpringBoot , SpringMVC ... 中间件 RPC , MQ...

    个性创业项目30个.doc

    - **增值服务**:举办读书会、文化交流等活动,增强客户粘性。 - **运营技巧**:合理定价,确保商品流转效率。 #### 10. 自助洗衣店 - **服务特色**:消费者自行操作洗衣流程,节省等待时间。 - **目标客群**:...

    leetcode下载-Android_AutoTest:Android_AutoTest

    [ReadingNotes(读书笔记)] [Project(项目)] 第六部分 [InterviewExperience(面试经验)] 有任何问题欢迎联系: 欢迎关注我的知乎账号: 微信公众号: 幼稚园老大哥 微博账号: 已同步到 拒绝任何形式的商业用途。

Global site tag (gtag.js) - Google Analytics