装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。对原有功能的增强。

我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

概述


  • 意图

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

  • 主要解决

    一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

  • 何时使用

    在不想增加很多子类的情况下扩展类。

  • 如何解决

    将具体功能职责划分,同时继承装饰者模式。

  • 关键代码

  1. Component 类充当抽象角色,不应该具体实现。
  2. 修饰类引用和继承Component类,具体扩展类重写父类方法。
  • 应用实例
  1. AOP面向切面编程,对于原有方法的增强,而又不影响原有的方法;
  2. 不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
  • 优点

    装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

  • 缺点

    多层装饰比较复杂。

  • 使用场景

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销。
  • 注意事项

    可代替继承。

实现


我们将创建一个Shape接口和实现了Shape接口的实体类。然后我们创建一个实现了Shape接口的抽象装饰类 ShapeDecorator,并把Shape对象作为它的实例变量。

RedShapeDecorator 是实现了ShapeDecorator的实体类。

DecoratorPatternDemo,我们的演示类使用RedShapeDecorator来装饰Shape对象。

  • step 1 创建一个接口

Shape.java

public interface Shape {
void draw();
}
  • step 2 创建实现接口的实体类

Rectangle.java

public class Rectangle implements Shape {

   @Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}

Circle.java

public class Circle implements Shape {

   @Override
public void draw() {
System.out.println("Shape: Circle");
}
}
  • step 3 创建实现了 Shape 接口的抽象装饰类

ShapeDecorator.java

public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape; public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
} public void draw(){
decoratedShape.draw();
}
}

-step 4 创建扩展了ShapeDecorator类的实体装饰类

RedShapeDecorator.java

public class RedShapeDecorator extends ShapeDecorator {

   public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
} @Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
} private void setRedBorder(Shape decoratedShape){
System.out.println("Border Color: Red");
}
public static void main(String[] args) { Shape circle = new Circle(); Shape redCircle = new RedShapeDecorator(new Circle()); Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("Circle with normal border");
circle.draw(); System.out.println("\nCircle of red border");
redCircle.draw(); System.out.println("\nRectangle of red border");
redRectangle.draw();
}
}
  • step 5 验证输出
Circle with normal border
Shape: Circle Circle of red border
Shape: Circle
Border Color: Red Rectangle of red border
Shape: Rectangle
Border Color: Red

设计模式学习心得<装饰器模式 Decorator>的更多相关文章

  1. 设计模式学习心得<代理模式 Proxy>

    在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 概述 意图 为其他对象提供 ...

  2. 设计模式系列之代理模式(Proxy Pattern)——对象的间接访问

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  3. 设计模式学习之代理模式(Proxy,结构型模式)(11)

    参考地址:http://www.cnblogs.com/zhili/p/ProxyPattern.html 一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访 ...

  4. 设计模式学习之代理模式(Proxy)

    一.代理模式的初衷 不想让客户端直接访问具体实现接口,客户端不应该直接访问具体实现,一般会涉及到以下四个对象 业务接口:定义客户端访问的接口,是实现类和代理类都需要实现的 实现类:实现了业务接口,真正 ...

  5. Java设计模式学习记录-代理模式

    代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问. 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起 ...

  6. 设计模式入门之代理模式Proxy

    //代理模式定义:为其它对象提供一种代理以控制对这个对象的訪问 //实例:鉴于书中给出的样例不太好.并且有些疑问,所以直接用保护代理作为实例 //要求,一旦订单被创建,仅仅有订单的创建人才干够改动订单 ...

  7. 学习笔记——代理模式Proxy

    代理模式,主要是逻辑和实现解耦.具体逻辑如何,由代理Proxy自己来设计,我们只需要把逻辑Subject交给代理即可. 主要应用场景,包括创建大开销对象时,使用代理来慢慢创建:远程代理,如网络不确定时 ...

  8. 《JAVA设计模式》之代理模式(Proxy)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式的结 ...

  9. javascript设计模式学习之六——代理模式

    一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...

  10. 设计模式学习心得<组合模式 Composite>

    组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结构型模式, ...

随机推荐

  1. Logparser介绍

    原文链接:https://www.cnblogs.com/Jerseyblog/p/3986591.html Logparser是一款非常强大的日志分析软件,可以帮助你详细的分析网站日志.是所有数据分 ...

  2. boost的named_mutex的一些坑

    最近遇到一个问题,程序在a用户下运行后,然后注销windows,登陆b用户,发现程序奔溃,抓了下堆栈,发现了boost的named_mutex一些细节,记录下 #include <boost/i ...

  3. python-day19 Django模板,路由分发,ORM

    @获取文件所有数据 request.FILES: request.POST.get('fafafa')#拿到文件名: user = request.POST.get('user',None)#用get ...

  4. Redis阻塞诊断基础

    slowlog Redis慢查询 slowlog 参数 slowlog-log-slower-than: 慢查询时间阈值,超过这个阈值的查询将会被记录,默认值10000,但是微妙,也即10毫秒. sl ...

  5. python基础之语句字符串

    python的种类: jpython                 java写的python ironpython            c#写的python cpython             ...

  6. 浅谈Tomcat和Servlet

    本文浅谈下对Tomcat和Servlet总体的理解,初学时有用过一段时间,但当时疲于应对如何xml配置和使用,对他们的理解就像是一个黑匣子.现在回顾一下帮助自己加深网络的理解.开始还是先推荐我看的文章 ...

  7. 导弹拦截问题(DP+贪心)

    1. 拦截导弹(Noip1999) 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度. ...

  8. mysql转移数据目录后无法启动问题

    最近在学习mysql,将mysql的数据目录文件路径/var/lib/mysql转移到/data/mysql,然后通过软连接方式关联. 1. ln -s /data/mysql /var/lib/my ...

  9. rsync镜像命令

    rsync -e 'ssh -p 19809' -av wwwroot root@3.3.3.3:/home/download/ 参数详解 编辑 -v, --verbose 详细模式输出 -q, -- ...

  10. yii2-redis 扩展详解

    安装yii2-redis composer require yiisoft/yii2-redis 修改config/web.php 的  components 配置 'cache' => [ / ...