3.Decorator Pattern(装饰者模式)
装饰者模式:
动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。
举例:
不知道大家学校的食堂是什么点餐制度(或者大家就直接想成吃火锅,我们要火锅料 + 配菜),我们学校的点餐是:主食大米 + 你想要吃的菜(每个菜都装在小碗中)。现在问题来了,我点的是大米(0.8元) + 红烧茄子(2.0元) + 荔枝肉(3.5元) + 一个鸡腿(3.5元) + 炒土豆(1.0元),一共10.8元。
这只是我想要吃的食品,每个同学点餐都不一样,所以价格会随着所点食物的不同而不同。还有一点就是我们点餐都要点米饭(这是规定,没有那么多理由,就是这么任性。其实不然,我们需要有个主对象去修饰),那么我们应该怎样实现这样的点餐计价方式呢?
生活中的实例:
有一家咖啡店,它提供给我们如下代码:
public abstract class Beverage{//饮料抽象类
String description = "Unknown Beverage";//饮料名称 public String getDescription(){//获取饮料名称的方法
return description;
} public abstract double cost();//饮料价格
}
Beverage
这家咖啡店有主饮料(相当于米饭):Espresso(浓缩咖啡1.99$)、HouseBlend(综合咖啡0.89$)、DarkRoast(深焙0.99$)、Decaf(低咖啡因1.05$)四种
还有各种配料:Milk(牛奶0.10$)、Mocha(摩卡0.20$)、Soy(豆浆0.15$)、Whip(奶泡0.10$)四种
咖啡店想要做出一个点饮料机器,可以点一种主饮料再从四种配料中任意选1到4中配料。该机器可以算出最后的总价,并且可以显示都点了那些东西。
分析:
主饮料全部继承自Beverage抽象类,因为店家已经给了Beverage抽象类,我们只能采用继承方式来实现四种主饮料类,如果没有给建议使用接口方式实现(多用组合,少用继承。)
主饮料我们只实现其中两种:
public class Espresso extends Beverage{//浓缩咖啡类 public Espresso(){
description = "Espresso";
} public double cost(){
return 1.99;
}
}
Espresso
public class HouseBlend extends Beverage{//综合咖啡类
public HouseBlend(){
description = "House Blend Coffee";
} public double cost(){
return .89;
}
}
HouseBlend
配料也继承自Beverage,不过我们在中间加一个桥梁,将主饮料和配料区别对待,这样对于以后的修改有好处:
public abstract class CondimentDecorator extends Beverage{//配料接口
public abstract String getDescription();
}
CondimentDecorator
所有配料都继承自上面的CondimentDecorator接口:
配料我们实现其中三种:
public class Mocha extends CondimentDecorator {//配料:摩卡类
Beverage beverage;//每个配料中都有一个Beverage对象,该对象存储的是配料修饰的产品。
//关键就在这个对象,最后结算的时候,我们可以调用该对象的getDescription和cost方法
//我称它为盒子里面套盒子 public Mocha(Beverage beverage){
this.beverage = beverage;
} public String getDescription(){
return beverage.getDescription() + ", Mocha";//调用beverage对象的getDescription()方法
} public double cost(){
return .20 + beverage.cost();//调用beverage对象的cost()方法
}
}
Mocha
public class Soy extends CondimentDecorator {
Beverage beverage; public Soy(Beverage beverage){
this.beverage = beverage;
} public String getDescription(){
return beverage.getDescription() + ", Soy";
} public double cost(){
return .15 + beverage.cost();
}
}
Soy
public class Whip extends CondimentDecorator {
Beverage beverage; public Whip(Beverage beverage){
this.beverage = beverage;
} public String getDescription(){
return beverage.getDescription() + ", Whip";
} public double cost(){
return .10 + beverage.cost();
}
}
Whip
测试类:
public class StarbuzzCoffee{ public static void main(String args[]){
Beverage beverage = new Espresso();//只点主饮料:Espresso
System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new HouseBlend();//点主饮料:HouseBlend
beverage2 = new Mocha(beverage2);//在主饮料中加入Mocha配料:HouseBlend + Mocha
beverage2 = new Soy(beverage2);//在饮料中加入Soy配料:HouseBlend + Mocha + Soy
beverage2 = new Whip(beverage2);//在饮料中加入Whip配料:HouseBlend + Mocha + Whip
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());//结算 Beverage beverage3 = new Whip( new Soy( new Mocha( new HouseBlend())));//这个和beverage2是一样的只是写法不同,认真观察
System.out.println(beverage3.getDescription() + " $" + beverage3.cost());//结算
}
}
StarbuzzCoffee
编译运行结果:
总结:
主饮料和配料都继承自相同的Beverage抽象类,不过为了区分主饮料和配料的不同,我们在配料和Beverage抽象类之间有多了一个CondimentDecorator接口。
主饮料实现时,只要getDescription()和cost()方法返回自己的名称和价格就好。配料中则多了一个Beverage对象,getDescription()和cost()方法不仅要返回自己的名称和价格,还要将自己修饰的Beverage对象的名称和价格一起算上。
在Java中的Java.io类中使用的就是装饰者模式,有兴趣可以自己搜索资料。
思想提炼:
1.对扩展开放,对修改关闭
3.Decorator Pattern(装饰者模式)的更多相关文章
- Decorator Pattern (装饰者模式)
装饰者模式( Decorator Pattern ) 意图 : 动态的给一个对象添加一些额外的功能,IO这块内容体现出了装饰模式,Decorator模式相比生成子类更为灵活. 角色 : 1)抽象构件角 ...
- Decorate Pattern 装饰者模式
装饰模式的定义: 动态地将责任附加到对象向,若要扩展功能,装饰模式提供了比继承更有弹性的替代方案. 遵循的设计原则是开闭原则,也是对扩展开放,对修改关闭. 下面是类图 示例代码 /** *定义被装饰者 ...
- Decorator(装饰)模式
1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继 ...
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
- java之装饰器模式
Decorator Pattern(装饰器模式),定义:Attach additional responsibilities to an object dynamically. Decorators ...
- 来杯咖啡-装饰者模式(Decorator)
前言 上篇[观察者模式]发布已经近一个月了,个人感觉反应并不太理想,因为大家响应都不是很积极,不知是文章那里写得有问题,而且也没有人提出过有价值的改进建议,多少感觉有些失望L!因为工作繁忙,所以不可能 ...
- [C++设计模式] decorator 装饰者模式
<head first>中 的样例:咖啡店有各种咖啡饮料,能够往咖啡里面加各种调料变成还有一种饮料.假设使用继承的方式来为每一种饮料设计一个类,代码的复杂度非常easy膨胀,并且会继承父类 ...
- PHP设计模式之装饰器模式(Decorator)
PHP设计模式之装饰器模式(Decorator) 装饰器模式 装饰器模式允许我们给一个类添加新的功能,而不改变其原有的结构.这种类型的类属于结构类,它是作为现有的类的一个包装 装饰器模式的应用场景 当 ...
- 设计模式系列之装饰模式(Decorator Pattern)
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原 ...
- 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)
在前两篇博客中详细的介绍了"策略模式"和“观察者模式”,今天我们就通过花瓶与鲜花的例子来类比一下“装饰模式”(Decorator Pattern).在“装饰模式”中很好的提现了开放 ...
随机推荐
- 【CF995F】 Cowmpany Cowmpensation
CF995F Cowmpany Cowmpensation Solution 这道题目可以看出我的代码能力是有多渣(代码能力严重退化) 我们先考虑dp,很容易写出方程: 设\(f_{i,j}\)表示以 ...
- 522. Longest Uncommon Subsequence II
Given a list of strings, you need to find the longest uncommon subsequence among them. The longest u ...
- 【友情链接】各位dalao的博客
同省神犇 HA队长 __stdcall HA chty_syq为文文讲过字符串 HA cdcq为文文讲过后缀数组① ② Bluesky007超强的 外省神犇 知名OIer黄学长 一个可爱的蓝孩子qwq ...
- js中获取当前页面的url
在js中可以通过下面的方式获取当前页面url的相关信息 var item = window.location // 返回的是对象, 这个对象里有各种关于url的信息 var url = window. ...
- spring cloud学习(二) 调用服务
spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign. Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了ri ...
- 跟着刚哥学Redis
NoSQL 简介 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL".是对不同于传统的关系型数据库的数据库管理系统的统称.它泛指非关系型的数据库.随着 ...
- C#6.0语言规范(十五) 委托
委托启用其他语言(如C ++,Pascal和Modula)已使用函数指针进行寻址的方案.但是,与C ++函数指针不同,委托是完全面向对象的,与成员函数的C ++指针不同,委托封装了对象实例和方法. 委 ...
- Python做web开发,推荐几个能立马上手的小项目
Python这门优美的语言是非常适合web开发的,基于Python的Django框架简单便捷且很强大. 那么作为新手该如何上手这门语言?一切不敲代码的学编程手段都是扯淡,今天就推荐一些适合新手练手的P ...
- shopify网站转化率优化之结账页checkout优化
昨天分享了“利用GOOGLE地图API实现shopify结账页checkout地址自动填写地址字段”是个非常屌的功能,但shopify默认的结账页checkout是这样的如图 [caption id= ...
- java操作数据库的基本方法
此次开发工具为eclipse,才有的数据库驱动是mysql-connector-java-5.1.8-bin.jar 第一步,在eclipse的工程目录中引用mysql驱动 驱动下载地址:https: ...