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. haproxy+keepalived实现web集群高可用性[转]

    负载均衡集群的概念 负载均衡是设计分布式系统架构必须要考虑的因素之一,它指的是通过调度分发的方式尽可能将“请求”.“访问”的压力负载平均分摊到集群中的各个节点,避免有些节点负载太高导致访问延迟,而有些 ...

  2. php跨form提交方法

    1.php curl function curlPost($url,$params) { $postData = ''; foreach($params as $k => $v) { $post ...

  3. c++ json cpp

    一 编译链接 1 在相应官网下载jsoncpp 2 解压得到jsoncpp-src-0.5.0文件 3 打开jsoncpp-src-0.5.0 -> makefiles -> vs71 - ...

  4. informatica 中的workflow连接mysql数据配置DSN

    先要下载mysqlodbc 一步步安装之后 ,再从管理工具里面找到ODBC,最后选择系统DSN,添加mysql驱动之后,进入添加编辑: 在workflow里面的配置连接字符串就写刚刚配置的连接名称 比 ...

  5. C语言中文件目录(一正二反)斜杠

    正斜杠unix“/” linux,安卓,苹果都是 windows是两个反斜杠“\\”,但现在也兼容了可以使用正斜杠“/”

  6. mysql数据库中,通过一条insert into语句,同时插入多个值

    需求描述: 今天在看一本mysql的书籍,发现一个mysql中insert into好用的技巧,就是通过 1条insert into语句,插入多行数据,而不是多个insert into语句.在此记录下 ...

  7. [hibernate]org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type setter

    org.hibernate.PropertyAccessException: Null value was assigned to a property of primitive type sette ...

  8. POJ 3093 Margaritas(Kind of wine) on the River Walk (背包方案统计)

    题目 Description One of the more popular activities in San Antonio is to enjoy margaritas in the park ...

  9. vue 组件库

    iView https://www.iviewui.com/ Radon UI https://luojilab.github.io/radon-ui/#!/ Element http://eleme ...

  10. org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException)

    在运行hadoop的程序时,向hdfs中写文件时候,抛出异常信息如下: Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hado ...