设计模式之装饰(Decorator)模式

(一)什么是装饰(Decorator)模式

  装饰模式,又称为包装模式,它以对客户端透明的方式扩张对象的功能,是继承关系的替代方案之一。
  装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

(二)装饰模式的角色

  1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象
  2)具体构件(Concrete component)角色:定义一个将要接受附加责任的类
  3)装饰角色(Decorator)角色:持有一个构建(Component)对象的实例
  4)具体装饰(Concrete decorator)角色:负责给构件对象添加功能。

(三)装饰模式的实现

  想象一下这样一种情况,定义了一个接口Car(代码如下),里边只包含一个方法move(),这个方法用来展示具体车的移动方式。

public interface Car {
void move();
}

  首先我们创建一个最普通的车RunCar(这里的普通指的是移动方式为陆地移动),实现这个接口。

public class RunCar implements Car {

    @Override
public void move() {
this.run();
} public void run() {
System.out.println("可以跑");
} }

  随着科技的进步,可能会有能够飞的车FlyCar,可能会有SwimCar,我们首先想到的实现方式就是继承,通过子类的实现扩展父类的功能,在这里指的是分别创建FlyCar类和SwimCar类实现Car接口。如果有这样一种需求,创建一种既能飞fly也能swim的FlySwimCar,这样该如何实现的,传统的继承能够实现,但一方面java只支持单继承,灵活性较差,另一方面,之前已经分别创建了FlyCar和SwimCar,如果再创建FlySwimCar会造成代码重复,想象一下,如果能够在FlyCar的基础上扩展swim功能就好了。

  恰巧,装饰着模式就能解决此类问题。

  这里我们的Component角色 指的就是Car接口,它既是被装饰类的父接口,也是装饰类的父接口。

  RunCar扮演的就是被装饰者的角色,它是Component角色的实现类。

  抽象装饰角色为CarDecorator,实现了Car接口,切内部包含一个Car的引用,用来保存被装饰的对象:

public abstract class CarDecorator implements Car  {
private Car car;
public CarDecorator(Car car) {
this.car = car;
} public Car getCar() {
return car;
} public void setCar(Car car) {
this.car = car;
} public abstract void move();

  具体抽象角色用于具体功能的扩展,在这里SwimCarDecorator为传进的汽车对象增加swim功能,FlyCarDecorator为传进的汽车对象增加fly功能。

public class SwimCarDecorator extends CarDecorator {

    public SwimCarDecorator(Car car) {
super(car);
} public void move() {
this.getCar().move();
this.swim();
} public void swim() {
System.out.println("可以游");
} }
public class FlyCarDecorator extends CarDecorator {

    public FlyCarDecorator(Car car) {
super(car);
} @Override
public void move() {
this.getCar().move();
this.fly();
} public void fly() {
System.out.println("可以飞");
} }

  这样以来,如果要创建一个会飞的汽车,那么把一个普通汽车传给FlyCarDecorator即可,如果创建一个会swim的车,把普通汽车传给SwimDecorator即可,如果想创建一个既会fly也会swim,只需把一个普通对的车传给FlyCarDecorator,再传给SwimDecorator即可。

public class Client {
public static void main(String[] args) {
Car runCar = new RunCar();
runCar.move();
System.out.println("-----------");
Car flyCar = new FlyCarDecorator(runCar);
flyCar.move();
System.out.println("-----------");
Car flySwimCar = new SwimCarDecorator(new FlyCarDecorator(new RunCar()));
flySwimCar.move();
}
}

(四)在什么情况下使用装饰模式

  需要扩展一个类的功能,或给一个类增加附加责任。
  需要动态地给一个对象增加功能,这些功能可以动态的撤销
  需要增加由一些基本功能排列则和而产生的非常大量的功能,从而使继承关系变得不显示。

(五)装饰模式的简化

  1)如果只有一个ConcreteComponent类而没有抽象的Component接口,可以把Decorator类设为ConcreteComponent的一个子类  
  2)如果只有一个ConcreteDecorator类,就没有必要定义Decorator类

(六)装饰模式的优缺点  

  优点:
    1)装饰模式与继承关系的目的都是扩展对象的功能,装饰模式可以提供比继承更多的灵活性。继承是静态的,而装饰是动态的。
    2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可是设计出很多不同行为的组合。
  缺点:
   使用装饰比使用继承需要更少数目的类,使用较少的类当然设计比较易于进行,但另一方面,装饰模式会产生比继承关系更多的对象,这些对象看上去都很相似,因此查错更为困难。

  总结:装饰者模式:是你还有你,多数拜托你

设计模式之装饰(Decorator)模式的更多相关文章

  1. C#设计模式(9)——装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  2. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  3. PHP设计模式之装饰器模式(Decorator)

    PHP设计模式之装饰器模式(Decorator) 装饰器模式 装饰器模式允许我们给一个类添加新的功能,而不改变其原有的结构.这种类型的类属于结构类,它是作为现有的类的一个包装 装饰器模式的应用场景 当 ...

  4. Java 设计模式泛谈&装饰者模式和单例模式

    设计模式(Design Pattern) 1.是一套被反复使用.多人知晓的,经过分类编目 的 代码设计经验总结.使用设计模式是为了可重用代码,让代码更容易维护以及扩展. 2.简单的讲:所谓模式就是得到 ...

  5. 实践GoF的23种设计模式:装饰者模式

    摘要:装饰者模式通过组合的方式,提供了能够动态地给对象/模块扩展新功能的能力.理论上,只要没有限制,它可以一直把功能叠加下去,具有很高的灵活性. 本文分享自华为云社区<[Go实现]实践GoF的2 ...

  6. 装饰(Decorator)模式

    1.装饰(Decorator)模式    动态给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更为灵活.Component是定义一个对象接口.可以给这些对象动态地添加职责.Concre ...

  7. 设计模式之装饰者模式-java实例

    设计模式之装饰者模式 需求场景 我们有了别人提供的产品,但是别人提供的产品对我们来说还不够完善,我们需要对这个产品的功能进行补强,此时可以考虑使用装饰者模式. 我们已经有了产品,而且这个产品的功能非常 ...

  8. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  9. [设计模式] 9 装饰者模式 Decorator

    转:http://www.jellythink.com/archives/171#prettyPhoto 什么是装饰模式? 在GOF的<设计模式:可复用面向对象软件的基础>一书中对装饰模式 ...

  10. 设计模式学习--装饰者模式(Decorator Pattern)

    概念: 装饰者模式(Decorator Pattern): 动态地将功能添加到对象,相比生成子类更灵活,更富有弹性. 解决方案: 装饰者模式的重点是对象的类型,装饰者对象必须有着相同的接口,也也就是有 ...

随机推荐

  1. Quartz监听的端口

    上海移通短信网关:556重庆移动短信网关:557消息中心后台维护服务:558网页订单数据同步服务:559基础数据同步程序:560短信数据扣除服务:565基础数据维护服务:589推送数据抓取服务:222 ...

  2. 智能指针之 weak_ptr

    1. weak_ptr 介绍 std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性("弱")引用.在访问所引用的对象指针前必须 ...

  3. [LUOGU] P2245 星际导航

    题目描述 sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系, ...

  4. centOS下SVN安装和配置

    1>SVN服务器端文件可见问题 在平时使用SVN时候,一直以为在客户提交文件,那么在服务器对应的版本库下面就会有相同文件.在自己搭建后,发现提交到服务器端文件完全看不见.... 这是由于SVN服 ...

  5. Xshell 配色方案 Ubuntu Solarized_Dark isayme

    前言 最近在用Ubuntu,发现它的配色方案挺好看的,所以查了下有没有大神做过Xshell的Ubuntu配色方案. 一看,果然还是有大佬做了这个的. 三套配色配置如下: 1. Ubuntu的Solar ...

  6. jenkins插件开发(二)

    https://wiki.jenkins.io/display/JENKINS/Extend+Jenkins http://commons.apache.org/proper/commons-jell ...

  7. stm32L011F3——串口实例

    /* STM32L0xx HAL library initialization: - Configure the Flash prefetch, Flash preread and Buffer ca ...

  8. 【UOJ#51】【UR #4】元旦三侠的游戏(博弈论)

    [UOJ#51][UR #4]元旦三侠的游戏(博弈论) 题面 UOJ 题解 考虑暴力,\(sg[a][b]\)记录\(sg\)函数值,显然可以从\(sg[a+1][b]\)和\(sg[a][b+1]\ ...

  9. http协议工作原理(转)

     WWW是以Internet作为传输媒介的一个应用系统,WWW网上最基本的传输单位是Web网页.WWW的工作基于客户机/服务器计算模型,由Web 浏览器(客户机)和Web服务器(服务器)构成,两者之间 ...

  10. 00030_ArrayList集合

    1.数组可以保存多个元素,但在某些情况下无法确定到底要保存多少个元素,此时数组将不再适用,因为数组的长度不可变 2.JDK中提供了一系列特殊的类,这些类可以存储任意类型的元素,并且长度可变,统称为集合 ...