Decorator模式又叫装饰者模式,这种模式是为了满足Java开发的“面向扩展开放,面向修改闭源”的开发原则设计出来的。

在装饰者模式中,不修改源类的代码,却能修改源类中方法的功能。下面就以Angelababy化妆为例,详细介绍一下为什么需要装饰者模式,以及装饰者模式怎么实现:

  • 先介绍angelababy类
package site.wangxin520.gof.decorator;

/**
* 装饰者模式
* baby化妆类
* @author wangXgnaw
*
*/
public class Angelababy { /**
* 画眉毛
*/
public void meimao(){
System.out.println("baby自己画眉毛");
} /**
* 画眼影
*/
public void yanying(){
System.out.println("baby自己画眼影");
} /**
* 点腮红
*/
public void saihong(){
System.out.println("baby自己画腮红");
} /**
* 画口红
*/
public void kouhong(){
System.out.println("baby自己涂口红");
} }

在baby类里面,有四个方法,分别对应着baby自己给自己化妆的步骤。

  • 装饰者模式测试类,首先是baby给自己化妆
package site.wangxin520.gof.decorator;

/**
* 装饰者模式的测试类
* @author wangXgnaw
*
*/
public class Test { public static void main(String[] args) { Angelababy ab =new Angelababy(); //baby给自己化妆
ab.meimao();
ab.yanying();
ab.saihong();
ab.kouhong(); } }
  • 结果是:

由此可见,baby自己给自己化妆成功。

虽然这样自己是能给自己化妆的,不过怎么也没有专业的化妆师给自己化妆的效果好。所以baby找来了一个专业的化妆师A。

  • DresserA装饰者模式的的第一种实现,继承
package site.wangxin520.gof.decorator;

/**
* 装饰者模式的装饰者
* 化妆师A
* @author wangXgnaw
*
*/
public class DresserA extends Angelababy{ /**
* 重写了画眼影的方法,在画眼影之后,又加上了刷睫毛
*/
@Override
public void yanying() {
super.yanying();
//后面输出有误,注意
        System.out.println("给anglebaby刷睫毛");
} /**
* 重写了涂口红的方法
* 在涂口红之前,给她涂了桃红色红
*/
@Override
public void kouhong() {
System.out.println("给anglebaby涂了桃红色的口红");
super.kouhong();
} }
  • 测试类
package site.wangxin520.gof.decorator;

/**
* 装饰者模式的测试类
* @author wangXgnaw
*
*/
public class Test { public static void main(String[] args) { //化妆师a给baby化妆
Angelababy ab=new DresserA(); //anglebaby化妆
ab.meimao();
ab.yanying();
ab.saihong();
ab.kouhong(); } }
  • 结果:

由此可见,baby的眼影和口红都不是自己画的了,而是别人帮她画的。这就是第一种继承的方法。不过这种方法是有局限性的,如果anglebaby类是final修饰的不可继承的话,那就尴尬了。另外,化妆师实际上是不能去继承被化妆的那个人的,如果化妆师继承了anglebaby而不是小海绵继承的话,黄晓明可能会哭晕在厕所!

下面就介绍第二种方法:面向接口开发

首先提取出一个公共接口,化妆的interface接口

  • MakeUp 化妆的接口
package site.wangxin520.gof.decorator;

/**
* 化妆的接口
* @author wangXgnaw
*
*/
public interface MakeUp { /**
* 画眉毛
*/
public void meimao(); /**
* 画眼影
*/
public void yanying(); /**
* 点腮红
*/
public void saihong();
/**
* 画口红
*/
public void kouhong(); }
  • 让anglebaby实现该接口
package site.wangxin520.gof.decorator;

/**
* 装饰者模式
* baby化妆类
* @author wangXgnaw
*
*/
public class Angelababy implements MakeUp{ /**
* 画眉毛
*/
@Override
public void meimao(){
System.out.println("baby自己画眉毛");
} /**
* 画眼影
*/
@Override
public void yanying(){
System.out.println("baby自己画眼影");
} /**
* 点腮红
*/
@Override
public void saihong(){
System.out.println("baby自己画腮红");
} /**
* 画口红
*/
@Override
public void kouhong(){
System.out.println("baby自己涂口红");
} }
  • DresserB 化妆师b,同样也实现这个接口。不过在构造化妆师B的时候,得把anglebaby传进来
package site.wangxin520.gof.decorator;

/**
* 化妆师B
* @author wangXgnaw
*
*/
public class DresserB implements MakeUp{ //用于保存化妆师B的顾客
private MakeUp makeUp=null; /**
* 在构造化妆师B的类的时候,传入顾客
* @param makeUp
*/
public DresserB(MakeUp makeUp) {
this.makeUp=makeUp;
} /**
* 实现化妆的类,当调用顾客对应的类的时候,实现的还是顾客的功能
* 当需要增加新功能时候,只需要在对应的方法前面或者后面实现即可
*/
@Override
public void meimao() {
makeUp.meimao();
} /**
* 化妆师B觉得涂眼影不好看,所以不涂了
* 只给baby贴了双眼皮贴
*/
@Override
public void yanying() {
System.out.println("贴双眼皮贴");
} /**
* 化妆师B想在baby涂腮红之前,就加上摸粉底
*/
@Override
public void saihong() {
System.out.println("摸粉底");
makeUp.saihong();
} @Override
public void kouhong() {
makeUp.kouhong();
} }
  • 测试类
package site.wangxin520.gof.decorator;

/**
* 装饰者模式的测试类
* @author wangXgnaw
*
*/
public class Test { public static void main(String[] args) { //化妆师B给baby化妆 Angelababy ab=new Angelababy(); DresserB db=new DresserB(ab); db.kouhong();
db.yanying();
db.saihong();
db.meimao(); } }
  • 结果为:

由此可见,装饰者模式生效了。

不过面向接口的这种装饰者模式也有一个小问题,那就是必须重写接口的实现类,并且在实现类里面调用传入参数的所有方法。

当接口中抽象方法很多的时候,这就很麻烦。

为了解决这种麻烦,就提出了一种新的设计模式,即当需要使用哪种方法的时候,就修饰哪种方法,否则就不改变。这种新的模式就是动态代理模式。后面我们将详细介绍!

设计模式之——Decorator模式的更多相关文章

  1. Java--23种设计模式之decorator模式

    装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性.动态给一个对象增加功能,这些功能可以再动态的撤消.增加由一些基本功能的排列组合而产生的非常大量的 ...

  2. 4)Javascript设计模式:Decorator模式

    function MacBook() { this.cost = function() { return 997; } } var macbook = new MacBook(); function ...

  3. 设计模式:decorator模式

    两点: 继承同一虚接口,实现数据一致性 桥接方式指向被装饰类 目的:在不改变被装饰类功能的前提下增加新功能 特点:继承是子类和父类强耦合,桥接是低耦合 例子: class Print //抽象接口 { ...

  4. 浅谈设计模式--装饰者模式(Decorator Pattern)

    挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...

  5. 设计模式---单一职责模式之装饰模式(Decorator)

    前提:"单一职责"模式 在软件组件的设计中,如果责任划分的不清晰,使用继承,得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任 典型模式(表现 ...

  6. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  7. 设计模式(十二)Decorator模式

    Decorator模式就是不断地为对象添加装饰的设计模式.以蛋糕为例,程序中的对象就相当于蛋糕,然后像不断地装饰蛋糕一样地不断地对其增加功能,它就变成了使用目的更加明确的对象. 首先看示例程序的类图. ...

  8. 常见设计模式的解析和实现(C++)之九—Decorator模式

    作用:动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. UML结构图: 抽象基类: 1)  Component :定义一个对象接口,可以为这个接口动态地 ...

  9. 《图解设计模式》读书笔记5-2 decorator模式

    目录 代码演示 模式的角色和类图 思路拓展 Decorator模式即装饰器模式,就是对类进行装饰,下面通过代码说明. 代码演示 代码展示的内容 有一个类StringDisplay:表示一句话,比如he ...

随机推荐

  1. CentOS 7在桌面添加快捷方式

    直接把 /usr/share/applications 对应的 xxx.desktop 文件复制到桌面就OK!比如要在桌面创建Google Chrome Browser的快捷方式,直接在找到 /usr ...

  2. centos6.5的软件安装,用户管理等

    1.软件的安装命令: 第一种:以 软件名.rpm 为结尾的二进制文件,这样的文件的安装 rpm -ivh 软件名.rpm i 是 install v 是校验 h 进度 卸载软件 是 rpm -e 软件 ...

  3. opengl 裁剪平面

    原帖地址:http://blog.sina.com.cn/s/blog_5ff6097b0100xqvr.html void glClipPlane(GLenum plane, const GLdou ...

  4. jQuery对象的链式操作用法分析

    可以使用下面的原则判断一个函数返回的时候是jQuery对象,即是否可以用于链式操作. 除了获取某些数据的函数,比如获取属性值"attr(name)",获取集合大小"siz ...

  5. PHPCMS v9设置文章的审核功能

    对于新建的站点,如果想设置会员发布的文章必须通过审核后才能发布,则需要以下几步来完成: 1.根据需要自定义管理员角色或选择已有角色. 步骤:设置->管理员设置->角色管理->权限设置 ...

  6. 虚幻4 - ARPG实战教程(第一季)

    在广受欢迎的的<虚幻4高速开发入门>视频教程之后.我收到了许多的反馈,当中大量的同学想要一个实战类的教程.于是,我花了一段时间准备之后,推出了新的一系列实战教程. 希望以深入浅出的方式.解 ...

  7. com.thoughtworks.xstream.converters.ConversionException

    使用webService调用接口,返回的是xml格式,运用xstream解析的时候,出现了如下的错误: Exception in thread "Timer-1" com.thou ...

  8. 安卓教程:提取APK程序里图片资源的方法

    有些APK程序里的图标.图片很漂亮,在使用程序时你可能会想,如果能把这些漂亮的图标.图片提取出来就好了,其实这是可以办到的,请看教程. 本教程以“电影超人”的APK安装包为例,其它APK程序的提取方法 ...

  9. CentOs 设置静态IP 方法[测试没问题]

    首先关闭VMware的DHCP: Edit->Virtual Network Editor 选择VMnet8,去掉Use local DHCP service to distribute IP ...

  10. iOS文件处理介绍(一)

    一.在Documents.tmp和Library中存储文件 Documents:用于存储应用程序中经常需要读取或写入的常规文件. tmp:用于存储应用程序运行时生成的文件.(随着应用程序的关闭失去了利 ...