文档章节

设计模式——装饰者模式:婚纱照收费的简单实现

AlanVision
 AlanVision
发布于 2016/10/20 09:41
字数 1020
阅读 3139
收藏 145

装饰者模式

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰者模式特点

  1. 装饰者和被装饰对象有相同的超类型。
  2. 你可以用一个或者多个装饰者包装一个对象。 
  3. 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它。
  4. 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
  5. 对象可以在任何时候被装饰,所以可以在运行时动态的,不限量的用你喜欢的装饰者来装饰对象。

装饰者模式类图

从上图可以看出,装饰者和被装饰者拥有共同的父类Componet,为了方便后面的扩展,我们加了一个装饰者父类Decorator,让Decorator去继承Componet,然后让众多装饰者去继承Decorator。

应用场景(婚纱照收费)

生活中符合装饰者模式的应用场景其实还挺多,就拿前阵子去拍婚纱照的经历来说吧,婚纱工作人员一般先会跟你整体说,拍什么样的场景,多少套衣服,怎么去收费,然后在不改变原有收费的前提下,会跟你说精修入册数量,每加一张,就加收多少钱。现在我们来把这个分级收费模式抽象一下,假如说,我们拍摄一张照片是40块钱,精修一张40块,入册10块。安插在装饰者模式中,照片本身就成了我们说的被装饰者(ConcreteComponet),而精修和入册则符合我们对装饰者的定义,分别为DecoratorA,DecoratorB。接下来我们来实现一下这个应用场景的类图结构。

  照片本身 照片入册 照片精修
费用 40 10 40

场景(婚纱照收费)类图

Format为装饰者父类与WeddingPhoto(被装饰者)共同继承了Photo。IsPhotoAlbum(入册)与PhotoWithPs(精修)为装饰者,共同修饰WeddingPhoto。他们都拥有共同的行为cost(),用于计算出价格,description属性主要用于记录信息,方便查看实现结果,可要可不要。

代码实现

共同抽象父类

package decorate.base;
/**
 * 照片父类
 * @author vision
 */
public abstract class Photo {
	private String description="";
	
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	/**
	 * 价格
	 * @param price
	 * @return
	 */
	public abstract Double cost();

}

装饰者抽象父类

package decorate.format;

import decorate.base.Photo;
/**
 * Format(照片规格)装饰者,扩展自Photo父类
 * @author vision
 */
public abstract class Format extends Photo{
	/**
	 * 描述
	 * @param description
	 * @return
	 */
	public abstract String getDescription();
}

被装饰者(婚纱照)

package decorate;

import decorate.base.Photo;
/**
 * 被装饰者:婚纱照
 * @author vision
 */
public class WeddingPhoto extends Photo{
	
	public WeddingPhoto() {
		setDescription(getDescription()+"WeddingPhoto(婚纱照)");
	}
	@Override
	public Double cost() {
		return 40.0;
	}

}

装饰者(入册)

package decorate.format;

import decorate.base.Photo;
/**
 * 装饰者:照片是否入册
 * @author vision
 */
public class IsPhotoAlbum extends Format{
	private Photo photo;
	public IsPhotoAlbum(Photo photo) {
		this.photo=photo;
	}
	@Override
	public String getDescription() {
		return photo.getDescription()+"+IsPhotoAlbum(入册)";
	}

	@Override
	public Double cost() {
		// TODO Auto-generated method stub
		return 10.0+photo.cost();
	}

}

装饰者(精修)

package decorate.format;

import decorate.base.Photo;
/**
 * 装饰者:照片精修
 * @author vision
 */
public class PhotoWithPs extends Format{
	private Photo photo;
	
	public PhotoWithPs(Photo photo){
		this.photo=photo;
	}
	
	@Override
	public String getDescription() {
		return photo.getDescription()+"+PhotoWithPs(精修)";
	}
	/**
	 * 照片精修,每张多加40块
	 */
	@Override
	public Double cost() {
		return 40.0+photo.cost();
	}

}

测试类

package decorate;

import decorate.base.Photo;
import decorate.format.IsPhotoAlbum;
import decorate.format.PhotoWithPs;

public class TestClass {
	public static void main(String[] args) {
		Photo weddingPhoto=new WeddingPhoto();
		//精修
		PhotoWithPs photoWithPs=new PhotoWithPs(weddingPhoto);
		System.out.println("最终选择的照片为:"+photoWithPs.getDescription());
		System.out.println("最终单价为:"+photoWithPs.cost());
		//入册
		IsPhotoAlbum isPhotoAlbum=new IsPhotoAlbum(photoWithPs);
		System.out.println("最终选择的照片为:"+isPhotoAlbum.getDescription());
		System.out.println("最终单价为:"+isPhotoAlbum.cost());
	}
}

输出结果

备注

参考资料:《Head First 设计模式》

相关文章:《设计模式——观察者模式:天气推送的两种实现》

《设计模式——策略模式:会员价格体系的简单实现

《福利送上,未满十八岁勿点》

© 著作权归作者所有

AlanVision
粉丝 116
博文 51
码字总数 17340
作品 0
深圳
程序员
私信 提问
加载中

评论(12)

AlanVision
AlanVision 博主

引用来自“梅公子”的评论

这图用啥工具画的,好清爽的感觉
visio
一号男嘉宾
一号男嘉宾
这图用啥工具画的,好清爽的感觉
AlanVision
AlanVision 博主

引用来自“karry2012”的评论

真心不错,赞!我要关注博主
谢谢,就喜欢你这样的,哈哈
karry2012
karry2012
真心不错,赞!我要关注博主
AlanVision
AlanVision 博主

引用来自“119333994”的评论

易于理解,赞!

然后,单身狗受到了成吨的伤害。。。
这。。。😰
119333994
119333994
易于理解,赞!

然后,单身狗受到了成吨的伤害。。。
AlanVision
AlanVision 博主

引用来自“Elven_Xu”的评论

学习了,最近想学习设计模式,开始跟踪楼主博客,期待

那我再接再厉,争取把剩下的都共享出来啊
Elven_Xu
Elven_Xu
学习了,最近想学习设计模式,开始跟踪楼主博客,期待
隔壁王大爷
隔壁王大爷
简单便于理解,真心不错
AlanVision
AlanVision 博主

引用来自“小李飞菜刀”的评论

写的简单,便于理解,赞

多谢支持
《JavaScript设计模式与开发实践》模式篇(12)—— 装饰者模式

在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但是继承的方式并不灵活, 还会带来许多问题:一方面会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之 改变;另一方...

嗨呀豆豆呢
2018/12/25
0
0
Java 中的 GoF 设计模式(第一部分)

为了理解 GoF(Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人组)的设计模式原理和历史,我制作了一个 10 分钟的短视频。(作为 PluralSight 作者试录的) 视频:https...

王桥修道院副院长
2017/02/13
2.7K
3
《JavaScript设计模式与开发实践》最全知识点汇总大全

系列文章: 《JavaScript设计模式与开发实践》基础篇(1)—— this、call 和 apply 《JavaScript设计模式与开发实践》基础篇(2)—— 闭包和高阶函数 《JavaScript设计模式与开发实践》模式...

嗨呀豆豆呢
01/04
0
0
《JavaScript设计模式与开发实践》原则篇(2)—— 最少知识原则

最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这 里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。 单一职责原则指导我们...

嗨呀豆豆呢
2018/12/30
0
0
Java 设计模式(14) —— 复合模式

一、复合模式 模式常一起使用,组合在一个设计解决方案中 复合模式在一个解决方案中结合两个或多个模式,能解决一般性或一系列的问题 二、示例 本次设计模式讲解中无代码示例,由于复合模式是...

磊_lei
2018/05/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

可能是国内第一篇全面解读 Java 现状及趋势的文章

作者 | 张晓楠 Dragonwell JDK 最新版本 8.1.1-GA 发布,包括全新特性和更新! 导读:InfoQ 发布《2019 中国 Java 发展趋势报告》,反映 Java 在中国发展的独特性,同时也希望大家对 Java 有...

阿里云官方博客
19分钟前
3
0
Spring Boot 2.x基础教程:Swagger静态文档的生成

前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了。如果您还不熟悉这块,可以先阅读: Spring Boot 2.x基础教程...

程序猿DD
22分钟前
3
0
《毅力》读书笔记

1.确信你全身心地投入 2.准备好为目标进行艰难的跋涉 3.通过减少需要使用毅力的情形,为将来的挑战做好准备 4.尽可能具体细致地确定你的目标和实现目标的过程 5.把挑战分解为小而易于管理的小...

lingch
23分钟前
3
0
zk中快速选举FastLeaderElection实现

选举涉及概念 服务器状态 投票 如何选择投票? 协议 选举 如何进行选举? epoch 发送者 接收者 发送队列 接收队列 服务器状态 public enum ServerState { LOOKING,寻找Leader状态,当服务处于...

writeademo
26分钟前
3
0
教你玩转Linux—磁盘管理

Linux磁盘管理好坏直接关系到整个系统的性能问题,Linux磁盘管理常用三个命令为df、du和fdisk。 df df命令参数功能:检查文件系统的磁盘空间占用情况。可以利用该命令来获取硬盘被占用了多少...

Linux就该这么学
29分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部