beverage

设计模式之装饰者模式

半世苍凉 提交于 2020-02-18 08:16:25
什么是装饰者模式? 装饰者模式以对客户透明的方式动态地给一个对象附加上更多的责任,装饰者模式相比生成子类可以更灵活地增加功能。 Component:一般是一个抽象类(也有可能不是),是一组有着某种用途类的基类,包含着这些类最基本的特性。 ConcreteComponent:继承自Component,一般是一个有实际用途的类,这个类就是我们以后要装饰的对象。 Decorator:继承自Component,装饰者需要共同实现的接口(也可以是抽象类),用来保证装饰者和被装饰者有共同的超类,并保证每一个装饰者都有一些必须具有的性质,如每一个装饰者都有一个实例变量(instance variable)用来保存某个Component类型的类的引用。 ConcreteDecorator:继承自Decorator,用来装饰Component类型的类(不能装饰抽象类),为其添加新的特性,可以在委托被装饰者的行为完成之前或之后的任意时候。 下面我们以星巴兹咖啡订单管理系统 管理、计算各种饮料的售价为例,对装饰者模式展开讨论。 设计思路及代码实现 继承 可能我们的第一印象就是继承。 首先定义一个咖啡基类 对于加糖的,加牛奶的,加摩卡的 ,加奶泡的,分别写一个子类继承 对于加糖,又加奶的写一个类,对于对于加糖,又摩卡的写一个类,对于对于加糖、又奶泡的写一个类,对于加糖,又加奶、摩卡的写一个类。

java设计模式-装饰者模式

百般思念 提交于 2020-02-09 05:27:05
这个模式花费了挺长时间,开始有点难理解,其实就是 定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。 设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。 要点: 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为 以点咖啡为例: 我们在点咖啡的时候通常会有这样的情况: 点了不同的咖啡会有不同的价格,此时我们需要一个咖啡的基类,不同的咖啡重写基类的cost()方法来实现自己的价格,但有时候我们点咖啡的时候会需要添加一些额外的调料,这个时候价格就变了,而这些额外的调料现在又是不确定的,如果提供过多的set()和get()方法来进行调料的添加又会出现新的问题,如果后续推出茶,汽水之类的饮料时,我们从基类那里继承过来很多没用的set和get方法 所以在这里我们采用不一样的做法:以饮料为主体,然后在运行时以调料来“装饰”饮料,比如说顾客想要 加摩卡和加奶泡的深培咖啡,那么,要做的是: 1:拿一个深培咖啡对象(DarkRoast) 2:以摩卡(Mocha)对象装饰它 3:以奶泡(Whip)对象装饰它 4:调用cost()方法,并依赖委托

装饰者模式

跟風遠走 提交于 2020-02-09 05:13:08
装饰者模式定义: 装饰者模式动态的将责任附加到对象上,若要扩展对象,装饰者模式提供了比继承更有弹性的替代方案。 装饰者模式类图: 说明: a) ConcreteComponent是我们要动态地加上新行为的对象,它扩展自Component; b) 每个组件都可以单独使用,或者被装饰者包装起来使用; c) 每个装饰者都“有一个”(包装一个)组件,也就是说,装饰者有一个实例变量以保存某个Component的引用; d) Decorator是装饰者共同实现的接口(也可以是抽象类); e) ConcreteDecorator有一个实例变量,可以记录所装饰的事物(装饰者包装的Component); f) 装饰者可以加上新的方法,新行为是通过在旧行为前面或后面做一些计算来添加的。 装饰者模式具体示例: 在购买咖啡时,可以在咖啡中加入各种调料,例如:蒸奶(Steamed Milk)、豆浆(Soy)、摩卡(Mocha)或覆盖奶泡。 咖啡店会根据所加入的调料收取不同的费用,所以咖啡店订单系统必须考虑到这些调料部分。 现在考虑用装饰者模式来完成这个订单系统,以实现饮料结算和描述接口。下图是采用装饰者模式的咖啡订单系统类图: 说明: HouseBlend、DarkRoast、Espresso和Decaf是四个具体的组件,每一个组件代表一种咖啡类型; Milk、Mocha

c++设计模式:装饰者模式(Decorator Pattern)

点点圈 提交于 2020-02-09 00:27:33
定义: 装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 场景: 我们购买咖啡的时候,可以要求在其中加入各种调料,例如:蒸奶、豆浆、摩卡或覆盖奶泡,而咖啡店也会根据所加入的调料收取不同的费用,所以当我们设计订单系统的时候就需要考虑到这些调料部分啦。顾客的需求不一,如果我们针对每种配方都声明一个类得话,系统的维护将会十分头疼。此时装饰者模式就派上用场啦。我们可以根据顾客的需要动态的扩展顾客定制的咖啡,让其加上不同的调料,最终计算出顾客所需缴纳的费用。它的实现有点类似于递归,在实际使用的时候可以慢慢体会。 类图: c++代码如下: 不使用指针版本: #include <iostream>#include <string>using namespace std;class Beverage{public: virtual ~Beverage() {}; virtual string getDescription(); // 必须是虚函数,否则会造成后期使用时描述显示不正确 virtual double cost() = 0;protected: string m_description;};class CondimentDecorator:public Beverage{public: virtual string getDescription()

设计模式3——装饰者模式

左心房为你撑大大i 提交于 2020-02-03 08:59:34
定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加弹性的解决方案。 1 引例_咖啡订单系统 1.1 最初设计。 如图1,首先创建一个Bevarage(饮料)的抽象类,店内所有的咖啡都继承这个类。description是成员变量,由子类设置,描述咖啡使用。 getDescription() 就是返回这个描述。 cost() 方法是抽象方法,由子类实现,计算价格使用。 最开始咖啡就有如下4个(对咖啡不太了解,中文名字错了不要在意):DarkRoast(超优深焙咖啡),Espresso(浓缩咖啡),Decaf(低卡咖啡),HouseBlend(混合咖啡) 但客人要求在咖啡里添加调料:Milk(奶),Soy(豆浆),Mocha(摩卡),每种调料都有单独的价钱,所以设计上又添加了这些,如图2。 这里我们可以看出问题,图2中只是列出了三种组合,我们可以想一下,这种组合是由很多种的,现在是4款咖啡,3种调料,在考虑到以后,可定会推出更多的咖啡和各种调料。这样维护起来,类会爆炸的,而且有的人还喜欢double份的Mocha,这样算的话类就会无穷无尽,而且物价是波动的,你还会修改价格,这样维护起来会死人的。 1.2 进一步改进 如图3,这次将调料加入 Bevarage 中的成员变量中,并加入相应的has和set方法, cost() 方法现在提供实现,计算出调料的价格

装饰模式(Decorate Pattern)

不想你离开。 提交于 2020-01-30 12:55:20
装饰模式(Decorate Pattern) 描述:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的代替方案 注意:装饰者和被装饰者必须是一样的类型 缺点:利用装饰着模式,常常造成设计中有大量的小类,可能会造成使用此API程序员的困扰 代码举例: class Beverage { public : virtual std :: string getDescription ( ) ; virtual float cost ( ) ; } class DarkRoast : public Beverage { public : virtual std :: string getDescription ( ) { return "DarkRoast" ; } virtual float cost ( ) { return 1.0 ; } } class CondimentDecorator : public Beverage { public : CondimentDecorator ( Beverage * pBeverage ) ; virtual std :: string getDescription ( ) ; virtual float cost ( ) ; Beverage * m_pBeverage ; } class Milk : public

Kotlin设计模式实现之装饰者模式(Decorator)

你离开我真会死。 提交于 2020-01-02 09:39:59
前言 今天是2020年的第一天,在这里祝大家元旦快乐!之前用 kotlin实现了策略模式 ,文中写到要多写几篇文章来加深以下对设计模式的理解。那么今天要写的看题目应该就知道了:装饰者模式(也叫装饰模式)。下面是装饰者模式的定义: 装饰者模式(Decorator) :在不改变对象自身的基础上,动态地给一个对象添加一些额外的职责。与继承相比,装饰者是一种更轻便灵活的做法。若要扩展功能,装饰者提供了比继承更有弹性的替代方法。 故事场景 小星刚毕业,到一家公司实习。今天来到公司后,一如既往地开始编写它的增删改查。 刚刚坐下打开电脑,技术锦鲤走了过来,小星内心开始发牢骚(锦鲤来干啥,每回它来都没好事)。锦鲤告诉小星,公司想要编写一个卖咖啡的系统,有不同种类的咖啡,需要能计算出咖啡的钱和区分咖啡的类别。 小星:没问题,很简单。 十分钟后,小星写出了它的第一版代码: 咖啡的基类: abstract class Beverage(var description: String = "Unknown Beverage") { //描述 open fun getDescriptions():String{ return description } //价钱 abstract fun cost():Double } 其他咖啡(子类): /** * 深度烘焙咖啡(星巴克) * * @author

案例分析:设计模式与代码的结构特性

你离开我真会死。 提交于 2019-12-08 22:34:30
设计模式-工厂模式 意图 :提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 主要解决 :主要解决接口选择的问题。 何时使用 :系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。 如何解决 :在一个产品族里面,定义多个产品。 关键代码 :在一个工厂里聚合多个同类产品。 应用实例 :工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。 优点 :当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。 缺点 :产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码

Golang 实现设计模式 —— 装饰模式

流过昼夜 提交于 2019-12-01 10:08:54
概念 “用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能” “动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活” 何时用 需要扩展一个类的功能,或给一个类增加附加责任 需要动态的给一个对象增加功能,且可以动态地撤销它 需要增加一些基本功能的排列组合而产生的大量的功能,而使得继承变得非常困难的时候 实现构件 抽象构件(Component) 表示“被”装饰的本体的抽象定义,这个定义通常是一个接口(Interface),定义了若干方法(能力),这些方法可以用来在被具体装饰角色(ConcreteDecorator)实现时改变原有构件本体的方法(能力),如原来本体伤害输出是 10,装饰角色把它再增加 10 而不会影响本体的原有逻辑(代码)。 具体构件(ConcreteComponent) 表示实现了抽象构件(Component)的对象,即将要接受附加能力的对象,本文中比喻的“本体”。 抽象装饰(Decorator) 持有一个抽象构件的实例(即具体构件),并定义(实现)与抽象构件接口一致的接口。抽象装饰的(部分)作用应该是应用了依赖倒置原则,在结构上使具体装饰(ConcreteDecorator)不要直接依赖于抽象构件,因为二者作用性质也不同,直接依赖灰常奇怪,就好像都是50岁的男子也不能把隔壁老王当成爸爸一样。 具体装饰

设计模式之装饰者模式

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-30 05:58:05
  今天我们来学习一下装饰者模式。作为一名程序猿,相信许多人都跟我一样,在平时写代码的过程中,习惯使用继承。但是继承有时候会出现非常严重的问题,不过,没担心。装饰者模式将会给爱用继承的我们一个全新的设计眼界! 一、星巴兹咖啡的故事   我们通过一个生动有趣的例子来引出我们今天的主角--装饰者模式。    1、 现在呢,有一个咖啡馆,它有一套自己的订单系统,当顾客来咖啡馆的时候,可以通过订单系统来点自己想要的咖啡。他们原先的设计是这样子的:    2、 此时、咖啡馆为了吸引更多的顾客,需要在订单系统中允许顾客选择加入不同调料的咖啡,例如:蒸奶(Steamed Milk)、豆浆(Soy)、摩卡(Mocha,也就是巧克力风味)或覆盖奶泡。星巴兹会根据所加入的调料收取不同的费用。所以订单系统必须考虑到这些调料部分。   下面是他们的第一次尝试:   这种设计肯定是不行的,简直分分钟把人逼疯的节奏,有木有!    3、 这时,有个人提出了新的方案,利用实例变量和继承,来追踪这些调料。     具体为:先从Beverage基类下手,加上实例变量代表是否加上调料(牛奶、豆浆、摩卡、奶泡……),      这种设计虽然满足了现在的需求,但是我们想一下,如果出现下面情况,我们怎么办,     ①、调料价钱的改变会使我们更改现有代码。     ②、一旦出现新的调料,我们就需要加上新的方法