当前位置: 首页 > news >正文

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

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

装饰者模式

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

装饰者模式特点

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

装饰者模式类图

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

应用场景(婚纱照收费)

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

 照片本身照片入册照片精修
费用401040

场景(婚纱照收费)类图

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 设计模式》

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

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

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

转载于:https://my.oschina.net/visionit/blog/761023

相关文章:

  • asp.net C#操作存储过程读取存储过程输出参数值
  • sync_binlog innodb_flush_log_at_trx_commit 浅析
  • 昂靠的由来[本博作者爆料]
  • js 中 空值赋值运算符 的用法
  • node学习系列之简单文件上传
  • 前端 关于汇率的计算
  • mongoDB 文档查询
  • 安装了python报错 或者执行 npm install 时报node-sass的各种相关错误 解决办法
  • 今天打开一个网站 FSO对象实例创建失败
  • 【LeetCode】5. Longest Palindromic Substring 最大回文子串
  • vu2响应式原理 代码分析
  • 希尔排序
  • vu3响应式原理 代码分析
  • Java Tomcat SSL 服务端/客户端双向认证(一)
  • vue3中 setup注意点
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 345-反转字符串中的元音字母
  • create-react-app项目添加less配置
  • egg(89)--egg之redis的发布和订阅
  • Java Agent 学习笔记
  • Median of Two Sorted Arrays
  • React-flux杂记
  • scrapy学习之路4(itemloder的使用)
  • vue脚手架vue-cli
  • 仿天猫超市收藏抛物线动画工具库
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 微服务核心架构梳理
  • 小程序开发之路(一)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 阿里云ACE认证学习知识点梳理
  • 阿里云重庆大学大数据训练营落地分享
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • #pragam once 和 #ifndef 预编译头
  • #预处理和函数的对比以及条件编译
  • (03)光刻——半导体电路的绘制
  • (二)斐波那契Fabonacci函数
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (论文阅读30/100)Convolutional Pose Machines
  • (论文阅读40-45)图像描述1
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)为C# Windows服务添加安装程序
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • ... 是什么 ?... 有什么用处?
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .form文件_一篇文章学会文件上传
  • .Mobi域名介绍
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .net 验证控件和javaScript的冲突问题
  • .net反编译的九款神器
  • .NET简谈设计模式之(单件模式)
  • @font-face 用字体画图标
  • @vue/cli 3.x+引入jQuery