Decorator,装饰。使用装饰模式可以在应用里动态地添加一些可选的功能。比如一家卖冰淇淋的商店里卖的圣代冰淇淋,不同的风味有不同的价格还有描述 .. 下面通过这个例子来理解一下装饰模式 ..
先添加个接口 .. 名字是 Icecream .. 不同类型的冰淇淋都可以实施这个接口 .. 接口里有两个方法,一个是 cost ,可以返回冰淇淋的价格 .. 还有一个是 description .. 会返回冰淇淋的描述 ..
再添加一种冰淇淋,名字是圣代 ... sundae .. 实施一下 Icecream 这个接口 .. 这样它里面应该有个 cost 方法 ... 返回的是它的价格,比如一个圣代冰淇淋卖 7 块钱 ..
还应该有个 description 方法 ... 返回的是一段描述 ... 圣代冰淇淋 ..
装饰
我们卖的这种圣代冰淇淋有不同的风味 .. 不同风味的价格会不太一样 .. 描述也会不一样 .. 这样我们可以添加一个 Decorator ... 它应该是个 abstract class,抽象类 .. 名字是 IcecreamFlavor .. 这个类要实施跟 Sundae 一样的接口 .. 就是 Icecream ..
里面添加一个 protected $icecream; 再添加一个构造函数 .. 会接收一个 Icecream 对象 .. 名字是 $icecream ..
让内部的这个 $icecream 等于传递过来的 $icecream ..
两个 abstract function ... 一个是 cost ... 还有一个是 description ..
再去添加一个可选的特性,或者功能 ... 或者叫装饰的项目 .. 它们各自都应该是个独立的 class ... 比如圣代冰淇淋有草莓风味 .. 可以添加一个类 .. 名字是 Strawberry,它要继承 IcecreamFlavor 这个抽象类 ..
里面先添加一个 cost 方法 ... 如果是草莓风味,我们就加两块钱 .. 返回 $this->icecream->cost() 加上 2 ..
再添加一个 description 方法 .. 如果是草莓风味,描述里面可以加上一个 +草莓 .. $this->icecream->description() . '+草莓'
下面再去添加一个装饰项目 ... 复制一下 ... 名字是 Chocolate ... 表示巧克力风味的冰淇淋 ... 顾客如果选择巧克力风味的话,就加上 3 块钱 .. 描述里面添加一个 +巧克力 ..
测试
再测试一下 ... 先做个 sundae 冰淇淋 .. new Sundae() ... 用一下 $sundae 的 description 方法,它会返回一段描述 .. 再用一下它的 cost 方法,它会返回价格 .. 后面再加上 块钱 ... 前面用一个 print .. 输出返回的结果 ..
回到命令行 ... 执行一下 .. 输出的是圣代冰淇淋 .. 7 块钱 ..
现在如果顾客要一个加草莓的圣代冰淇淋 .. 我们可以做一个 $strawberry_sundae .. new Strawberry .. 然后把上面做好的这个普通的圣代交给它 .. 这样出来的就是加草莓的圣代冰淇淋
输出 strawberry_sundae->description ... 还有 strawberry_sundae->cost
执行一下 ... 这回输出的是圣代冰淇淋+草莓 9 块钱 ..
假设顾客这回要的是加草莓还有加巧克力的冰淇淋 .. 我们可以再做一个 $chocolate_strawberry_sundae .. new 一个 Chocolate,然后把上面做好的 草莓圣代交给这个方法..
输出 $chocolate_strawberry_sundae 的 cost ... 还有 $chocolate_strawberry_sundae 的 description ..
回到命令行 ... 再执行一下 ... 这回输出的是 圣代冰淇淋+草莓+巧克力12块钱 ...
你可以使用这种方法,去创建更多不同种类,不同风味的冰淇淋 ...