介绍者模式将责任动态地附加到对象上。为了扩展功能,装饰器提供了比继承更灵活的选择。思维导图
有这样一个制作餐厅点餐系统的项目。起初,代码结构是这样的。前面有很多饮料的继承类,但是现在的问题是牛奶的价格上涨了,所以我们要调整所有相关的类,比如牛奶和sugarandmilk,这样的类很多,需要逐个修改类中的方法。——开发商每次都做这种事,他们都快疯了!所以我们需要改变现有的结构。下面的图都是草图,但实际的图没有那么简单。
设计问题:1。品类数量爆炸,品类多,难以维护;2.整个设计呆板;3.基类添加的新函数不能用于子类;重用类方法有很多方法,比如继承、组合和委托。为什么总是习惯继承?我看Zend Framework也有这个习惯!每次找到对应的方法,总会出现。3354题外话!经过小组学习,我们决定把基础课拿出来。比如我们把咖啡做成一个单独的类,其他的咖啡,比如牛奶咖啡和甜咖啡,我们只把材料打包成一个单独的类。改进设计: 。
详细说明1“对于饮料,我们直接继承饮料类,直接将报价写入饮料类;2.对于一些需要添加调味品的特殊饮品,我们做累加运算。比如我要一杯牛奶咖啡,那么总价=咖啡价格和牛奶价格3,就很容易知道不同饮料的价格。复制代码如下:php抽象类饮料{ public $ _ name抽象公共功能成本();}//修饰类coffee扩展到{ public function _ _ construct(){ $ this-_ name=' coffee ';}公共函数Cost(){ return 1.00;} }//以下三个类是decorator相关的类:类压缩decorator扩展到{ public function _ _ construct(){ $ this-_ name=' compressed ';}公共函数Cost(){ return 0.1;} } class Milk扩展了CondimentDecorator { public $ _饮料;公共函数_ _ construct($饮料){ $ this-_ name=' Milk ';if($饮料实例of饮料){ $ this-_饮料=$饮料;}否则退出(“失败”);}公共函数Cost(){ return $ this-_饮料-Cost()0.2;Sugar类扩展了CondimentDecorator { public $ _饮料;public function _ _ construct($饮料){ $ this-_ name=' Sugar ';if($饮料实例of饮料){ $ this-_饮料=$饮料;} else { exit(' Failure ');} }公共函数Cost(){ return $ this-_饮料-Cost()0.2;}} //测试用例//1。喝杯咖啡$ Coffee=new Coffee();//2.加点牛奶$咖啡=新牛奶($咖啡);//3.加点糖$咖啡=新糖($咖啡);Printf('Coffee Total:%0.2f元n ',$ Coffee-Cost());1.装饰者(牛奶)和装饰者(咖啡)必须是同一类型。目的是装饰者必须替换被装饰的人。2.添加行为:当装饰器和组件被组合时,新的行为被添加。题目: 1。使用继承来设计子类行为是在编译时静态确定的,所有子类都将继承相同的行为。比如我想学点功夫,看你小子会不会太极拳。我只需要继承你,我就是太极川——。这一刻,我将成为你的儿子。看来继承是要付出代价的。2.组合,我们可以扩展对象的行为,并在运行时动态扩展它们。通过使用组合,我们可以随时将设计超类时没有想到的方法添加到对象中,而无需更改现有代码。比如老子现在没有内力,所以吸收了僧尼道士的内力(行为对象)。在斗争(运行时间)中,老子可以随时使用不同的内力,但他不能随意吸收内力,否则你会走火入魔!3.类应该对扩展开放,对修改关闭。如果我们在decorator模式中设计每个部分,对整个框架来说会有点浪费,而且会让代码更加困难。什么时候使用这种模式?我们通常在经常变化的地方使用它。那我们怎么知道哪些地方变化频繁呢?这需要我们的经验和您对您所在行业的了解。建议大家平时多看看例子。4.装饰器模式为设计注入了灵活性,但同时也给设计增加了大量的子类别,偶尔会让其他人难以理解设计。5.使用装饰器模式时,要特别小心插入的装饰器。因为装饰器模式依赖于特定的类别。6.如果我们想很好地使用装饰器模式,我们必须一起使用工厂模式和生成器模式,但是今天我们只讨论装饰器模式。如果想了解更多,请听下细分。参考: 《head first 设计模式》。