装饰器模式(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. mybaties插件生成代码

    指定插件运行什么xml,关于如何用idea创建一个maven项目,可以看我以前写的博客 <?xml version="1.0" encoding="UTF-8&qu ...

  2. 2. spring定时任务

    1.添加命名空间 <!-- 定时注解驱动 --> <task:annotation-driven /> <!-- 进行定时任务的类,将其定义为一个bean --> ...

  3. spring boot 整合quartz ,job不能注入的问题

    在使用spring boot 整合quartz的时候,新建定时任务类,实现job接口,在使用@AutoWire或者@Resource时,运行时出现nullpointException的问题.显然是相关 ...

  4. Caused by: java.lang.IllegalArgumentException: argument type mismatch

    下面是我的报错信息 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java: ...

  5. Delphi调用C#编写的WebService 注意事项

                            返回的字段值区分大小写,c#和Delphi的字段要一致

  6. Spring中利用applicationContext.xml文件实例化对象和调用方法

    Spring中实例化对象和调用方法入门 1.jar包和xml的准备 已上传至百度云盘,链接: https://pan.baidu.com/s/1CY0xQq3GLK06iX7tVLnp3Q 提取码: ...

  7. BASH_SOURCE

    在C/C++中,__FUNCTION__常量记录当前函数的名称.有时候,在日志输出的时候包含这些信息是非常有用的.而在Bash中,同样有这样一个常量FUNCNAME,但是有一点区别是,它是一个数组而非 ...

  8. [Kafka] |FAIL|rdkafka#producer-1 : Receive failed: Disconnected

    Why am I seeing Receive failed: Disconnected? 1. broker 的空闲连接回收器关闭不活跃连接. 由 broker 的配置属性 connections. ...

  9. 问题:页面输出正常,php写入sqlserver乱码/空白。

    问题一:php连接sqlsever2005,输入中文,然后查询sqlserver中对应的数据,由于提交中文是UTF-8,而sqlserver的中文为GBK,所以字段无法匹配,没有查询结果. 问题二,p ...

  10. tensorflow,object,detection,在model zoom,新下载的模型,WARNING:root:Variable [resnet_v1_50/block1/unit_3/bottleneck_v1/conv3/BatchNorm/gamma] is not available in checkpoint

    现象: WARNING:root:Variable [resnet_v1_50/block1/unit_1/bottleneck_v1/conv1/BatchNorm/beta] is not ava ...