设计模式之禅之设计模式-装饰者模式

一:装饰模式的定义
        --->动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
        --->如果大家还记得代理模式,那么很容易看懂这个类图,装饰类的作用也就是一个特殊的代理类.
        --->在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件

二:装饰模式的角色
        ● Component抽象构件
                Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象
        ● ConcreteComponent 具体构件
                ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
        ● Decorator装饰角色
                一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private变量指向Component抽象构件。
        ● 具体装饰角色
                ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰成其他东西

三:装饰模式的优缺点
        
装饰模式的优点
        ● 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
        ● 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
        ● 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此。

装饰模式的缺点
        ●对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量吧,因此,尽量减少装饰类的数量,以便降低系统的复杂度。

四:装饰模式的应用场景
        ● 需要扩展一个类的功能,或给一个类增加附加功能。
        ● 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
        ● 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。

五:装饰模式的最佳实践
        装饰模式是对继承的有力补充。你要知道继承不是万能的,继承可以解决实际的问题,但是在项目中你要考虑诸如易维护、易扩展、易复用等,而且在一些情况下你要是用继承就会增加很多子类,而且灵活性非常差,那当然维护也不容易了,也就是说装饰模式可以替代继承,解决我们类膨胀的问题。同时,你还要知道继承是静态地给类增加功能,而装饰模式则是动态地增加功能,
        装饰模式还有一个非常好的优点:扩展性非常好。在一个项目中,你会有非常多的因素考虑不到,特别是业务的变更,不时地冒出一个需求,尤其是提出一个令项目大量延迟的需求时,那种心情是相当的难受!装饰模式可以给我们很好的帮助,通过装饰模式重新封装一个类,而不是通过继承来完成

六:装饰模式的例子

【1】抽象角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 抽象角色(装饰模式必不可少)
 4  * @author sxf
 5  *
 6  */
 7 public abstract class Component {
 8     //抽象的方法
 9     public abstract void operate();
10 }

【2】被装饰的真正角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 被装饰的真正角色
 4  * @author sxf
 5  *
 6  */
 7 public class ConcreteComponent extends Component {
 8
 9     @Override
10     public void operate() {
11         System.out.println("ConcreteComponent.operate(真正做的核心事情");
12     }
13
14
15 }

【3】装饰者的抽象角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 抽象装饰者
 4  * @author sxf
 5  *
 6  */
 7 public abstract class Decorator extends Component{
 8     //被装饰者
 9     private Component component = null;
10
11     //通过构造函数传递被装饰者
12     public Decorator(Component component){
13         this.component=component;
14     }
15
16     //调用被装饰者真正的目的
17     @Override
18     public void operate() {
19         this.component.operate();
20     }
21
22 }

【4】装饰者1的角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 装饰者1
 4  * @author sxf
 5  *
 6  */
 7 public class ConcreteDecorator1 extends Decorator{
 8
 9    public ConcreteDecorator1(Component component) {
10         super(component);
11     }
12
13     @Override
14     public void operate() {
15         System.out.println("ConcreteDecorator1.operate()装饰者1做了一些事情");
16         super.operate();
17         System.out.println("ConcreteDecorator1.operate()装饰者1做了一些事情");
18     }
19
20
21 }

【5】装饰者2的角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 装饰者2
 4  * @author sxf
 5  *
 6  */
 7 public class ConcreteDecorator2 extends Decorator {
 8
 9     public ConcreteDecorator2(Component component) {
10         super(component);
11     }
12
13     @Override
14     public void operate() {
15         System.out.println("ConcreteDecorator2.operate(装饰者2做了一些事情)");
16         super.operate();
17         System.out.println("ConcreteDecorator2.operate(装饰者2做了一些事情)");
18     }
19
20
21
22 }

【6】客户端测试类的角色

 1 package com.yeepay.sxf.template12;
 2 /**
 3  * 测试类
 4  * @author sxf
 5  *
 6  */
 7 public class ClientTest {
 8
 9     public static void main(String[] args) {
10         //真正的被装饰者
11         Component component=new ConcreteComponent();
12         //装饰者1装饰真正的装饰者
13         Component component2=new ConcreteDecorator1(component);
14         //装饰者2装饰装饰者1
15         Component component3=new ConcreteDecorator2(component2);
16         //执行装饰者2
17         component3.operate();
18         /**
19          * 执行结果
20          * ConcreteDecorator2.operate(装饰者2做了一些事情)
21          * ConcreteDecorator1.operate()装饰者1做了一些事情
22          * ConcreteComponent.operate(真正做的核心事情
23          * ConcreteDecorator1.operate()装饰者1做了一些事情
24          * ConcreteDecorator2.operate(装饰者2做了一些事情)
25          */
26     }
27 }

时间: 2024-08-05 09:56:59

设计模式之禅之设计模式-装饰者模式的相关文章

设计模式(十):装饰者模式

在<JavaScript设计模式>介绍中,装饰者模式跟Mixin(混入)模式相比,是另一种可行的对象子类化(Mixin模式干的事)的替代方案. 装饰者(Decorator)模式 定义: 给对象动态添加额外的功能.向基本对象添加(装饰)属性或方法,而不是进行子类化,它较为精简. 使用场景: java IO 流是典型的装饰模式. PS:应用程序包含需要大量不同类型对象的功能. 例子: // The constructor to decorate function MacBook() { this.

《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

装饰者模式是JDK中另一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源码,也是为了学习大牛们的设计思路.----题记 设计模式 观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新. 装饰者模式:动态地将责任附加到对象上.若要扩展功能,装饰者提供比继承者更有弹性的替代方案. 设计原则 (1)封装变化. (2)多用组合,少用继承. (3)针对接口编程,而不是

设计模式(五): 装饰者模式

装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类. 介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:一般的,我们

设计模式解密(9)- 装饰者模式

1.简介 定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 拆分定义,总结特点:   1.不改变原类文件. 2.不使用继承. 3.动态扩展. 主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀. 何时使用:在不想增加很多子类的情况下扩展类. 如何解决:将具体功能职责划分,同时继承装饰者模式. 英文:Decrator 类型:结构型模式 2.类图

菜鸟版JAVA设计模式—从火锅底料到装饰器模式

今天开始学历了JAVA设计模式中的装饰模式,照例还是写下自己理解的心得吧. 装饰器模式,啥是装饰器模式?带着这个问题,咱们好好的去火锅店吃个火锅. "老板,来份全辣锅底,不要给我用装饰器模式来配料!"我特地狠狠的强调了最后一句话. 不到一会,老板给我端来了一个火锅和几个盘子,火锅里装了盐水,而盘子里放了辣椒,花椒,茴香,大蒜等佐料.......... 这时候大家可能就需要问了,这咋吃啊...难道让我自己配料么? 这便是是我们的矛盾了!客户需要的一盘已经配好料的火锅汤底,但是我们初期给用

每天一个设计模式(3):装饰者模式

3.装饰者模式 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 一.问题引入 咖啡店的类设计: 一个饮料基类,各种饮料类继承这个基类,并且计算各自的价钱. 饮料中需要加入各种调料,考虑在基类中加入一些布尔值变量代表是否加入各种调料,基类的cost()中的计算各种调料的价钱,子类覆盖cost(),并且在其中调用超类的cost(),加上特定饮料的价钱,计算出子类特定饮料的价钱. 缺点:类数量爆炸.基类加入的新功能并不适用于所有的子类.调料价钱的改变.新调料的

设计模式(三):装饰器模式

一.概述 装饰器模式动态地将责任附加到对象上.想要扩展功能,装饰者提供了有别于继承的另一种选择.简单描述就是包装对象,让对象提供新的行为. 二.解决问题 当一个类想要获得一个行为,我们会想到面向对象四大特性之一的继承,继承能够让子类从父类中获得行为,实现很好的代码复用.但这种继承而来的行为是在编译时静态决定的,而且所有的子类都会继承相同的行为.如果我们想要扩展对象的行为,就要创建一个子类来修改父类的方法(也就是覆盖父类行为),每扩展一个行为就要创建一个子类,这样会带来很多问题.第一,如果需要扩展

设计模式总结篇系列:装饰器模式(Decorator)

在面向对象设计过程中,经常会遇到需要对现有的类的功能进行扩展,通常我们可以采用继承的方式.例如老罗最近在做手机,一开始需要定义手机所应具有的功能: 1 interface Phone{ 2 3 public void tel(); 4 5 public void sms(); 6 7 } 在此,为简单起见,只是定义了接打电话和收发短信功能. 然后,老罗开始造手机,经过两年艰苦努力,第一代手机T1终于面世了,很高兴的开了发布会,反响还不错. 1 class T1 implements Phone{

设计模式之禅之设计模式-桥梁模式

一:桥梁模式定义        --->桥梁模式(Bridge Pattern)也叫做桥接模式,是一个比较简单的模式        --->将抽象和实现解耦,使得两者可以独立地变化. 二:桥梁模式角色 ● Abstraction——抽象化角色        它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类.● Implementor——实现化角色        它是接口或者抽象类,定义角色必需的行为和属性.● RefinedAbstraction——修正抽象