Java设计模式系列之装饰者模式
装饰者模式的定义
动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
装饰者模式的UML类图

一般来说装饰者模式有下面几个参与者:
- Component:装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为
- ConcreteComponent:定义具体对象,即被装饰者
- Decorator:抽象装饰者,继承自Component,从外类来扩展ConcreteComponent。对于ConcreteComponent来说,不需要知道Decorator的存在,Decorator是一个接口或抽象类
- ConcreteDecorator:具体装饰者,用于扩展ConcreteComponent
注:装饰者和被装饰者对象有相同的超类型,因为装饰者和被装饰者必须是一样的类型,这里利用继承是为了达到类型匹配,而不是利用继承获得行为。
利用继承设计子类,只能在编译时静态决定,并且所有子类都会继承相同的行为;利用组合的做法扩展对象,就可以在运行时动态的进行扩展。装饰者模式遵循开放-关闭原则:类应该对扩展开放,对修改关闭。利用装饰者,我们可以实现新的装饰者增加新的行为而不用修改现有代码,而如果单纯依赖继承,每当需要新行为时,还得修改现有的代码。
example:
/**
* @author yaoshw
*/
public class TestMyIdea {
public static void main(String[] args) { //不添加任何调料的饮料A
Beverage beverage = new APart();
System.out.println("Apart:" + beverage.getDescription() + "," + beverage.cost()); //添加摩卡调料的饮料B
Beverage beverage1 = new Mocha(new BPart());
System.out.println("Bpart:" + beverage1.getDescription() + "," + beverage1.cost()); //添加双份摩卡的饮料C Beverage beverage2 = new Mocha(new Mocha(new CPart()));
System.out.println("Cpart:" + beverage2.getDescription() + "," + beverage2.cost()); //添加一份摩卡、一份豆浆的饮料D Beverage beverage3 = new Soy(new Mocha(new DPart()));
System.out.println("Dpart:" + beverage3.getDescription() + "," + beverage3.cost()); }
} /**
* 抽象类,相当于Component:cost方法和getDescription方法
*/
abstract class Beverage { String description = "UnKnownBeverage"; public String getDescription() {
return description;
} public abstract double cost();
} abstract class CondimentDerector extends Beverage {
@Override
public abstract String getDescription();
} /**
* 具体装饰者:摩卡
*/
class Mocha extends CondimentDerector { /**
* 保留基类的引用,以便于组合装饰者行为
*/
Beverage beverage; public Mocha(Beverage beverage) {
this.beverage = beverage;
} @Override
public double cost() {
return beverage.cost() + 2;
} @Override
public String getDescription() {
return beverage.getDescription() + ",monka";
}
} /**
* 具体装饰者:豆浆
*/
class Soy extends CondimentDerector { Beverage beverage; public Soy(Beverage beverage) {
this.beverage = beverage;
} @Override
public double cost() {
return beverage.cost() + 3;
} @Override
public String getDescription() {
return beverage.getDescription() + "soy";
}
} /**
* 调料A
*/
class APart extends Beverage { public APart() {
description = "Apart";
} @Override
public double cost() {
return 19.5;
}
} /**
* 调料B
*/
class BPart extends Beverage { public BPart() {
description = "Bpart";
} @Override
public double cost() {
return 20.5;
}
} /**
* 调料C
*/
class CPart extends Beverage { public CPart() {
description = "Cpart";
} @Override
public double cost() {
return 21.5;
}
} /**
* 调料D
*/
class DPart extends Beverage { public DPart() {
description = "Dpart";
} @Override
public double cost() {
return 22.5;
}
}
Java设计模式系列之装饰者模式的更多相关文章
- JAVA设计模式之【装饰者模式】
JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- JAVA设计模式初探之装饰者模式
定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种 ...
- java进阶系列之装饰器模式
1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...
- java设计模式-观察者模式,装饰者模式
1.1定义 慨念:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 即:主题和观察者定义了一对多的关系,观察者依赖于主题,只要主题发生变化,观察者就 ...
- Java设计模式系列之动态代理模式(转载)
代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...
- Java设计模式系列之责任链模式
责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道 ...
- Java设计模式系列3--抽象工厂模式(Abstract Factory Method)
2014-02-26 10:55:47 声明:本文不仅是本人自己的成果,有些东西取自网上各位大神的思想,虽不能一一列出,但在此一并感谢! 工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果 ...
随机推荐
- Linux学习-实验楼(1)
1.Shell:命令解释器 2.Linux技能树 3.X11:X窗口系统,其本身只是工具包及架构协议,Xorg是x架构规范的一个实现体,是实现了x协议规范的一个提供图形界面的服务器 4.终端本质上是对 ...
- springboot邮件发送与接收读取
发送邮件 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...
- 转: ffmpeg循环推流方法
from: https://blog.csdn.net/weiyuefei/article/details/64125208 ffmpeg循环推流方法 You should be able to u ...
- 树莓派raspberry pi配置无线路由器AP
raspi-config进入系统配置面板 进行 Expand Filesystem 扩展文件系统否则备份系统的时候备份文件会急速膨胀. (1)配置网络环境nano /etc/network/inte ...
- Web Workers 简介
web worker 介绍:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers web ...
- PL/SQL学习笔记之包
一:包 包是由一组相关的函数,过程,变量,游标等PL/SQL程序设计元素的组合而成的一个PL/SQL程序单元,相当于Java中的类. 包的主要作用是封装:把相同或相似的东西归类,方便维护和管理,提高开 ...
- 内核中的锁机制--RCU
一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了 ...
- 关于VC预定义常量_WIN32,WIN32,_WIN64
VC2012 下写 Windows 程序时,有时需要判断编译环境.在之前的文章<判断程序是否运行在 Windows x64 系统下.>里说过如何在运行期间判断系统环境,但在编译时如何判断? ...
- What’s new for Spark SQL in Apache Spark 1.3(中英双语)
文章标题 What’s new for Spark SQL in Apache Spark 1.3 作者介绍 Michael Armbrust 文章正文 The Apache Spark 1.3 re ...
- MySQL查询库和表占用的硬盘空间大小
在mysql中有一个默认的数据表information_schema,information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,表栏的数据类型与访问 ...