装饰者模式是对原有类进行多次附加,比单纯的继承更加灵活的组和。
本例参照网上黄焖鸡点加小菜的实例来讲解。
生活中不同的人喜欢加不一样的小菜,如不用装饰者模式,肯定要加一堆的if else。长期下去不利于代码的维护。
菜品抽象类
abstract class Food {
public $desc = "菜品";
public $price = 0;
public function getPrice() {
return $this -> desc . ":" . $this -> price;
}
public function getDesc() {
return $this -> desc;
}
abstract public function cost();
}
装饰者的抽象类
abstract class FoodDecorator extends Food {
public $obj;
public function __construct($obj) {
$this -> obj = $obj;
}
}
菜品类
class Rice extends Food {
public $desc = "黄焖鸡";
public $price = 20;
public function cost() {
return $this -> price;
}
}
使用装饰者加鸡蛋类
class Egg extends FoodDecorator {
public $desc = "鸡蛋";
public $price = 2;
public function cost() {
return $this -> obj -> cost() + $this -> price;
}
public function getDesc() {
return $this -> obj -> getDesc() . " + " . $this -> desc;
}
public function getPrice() {
return $this -> obj -> getPrice() . " + " . $this -> desc . ":" . $this -> price;
}
}
使用装饰者加蔬菜类
class Veg extends FoodDecorator {
public $desc = "蔬菜";
public $price = 1.5;
public function cost() {
return $this -> obj -> cost() + $this -> price;
}
public function getDesc() {
return $this -> obj -> getDesc() . " + " . $this -> desc;
}
public function getPrice() {
return $this -> obj -> getPrice() . " + " . $this -> desc . ":" . $this -> price;
}
}
点餐系统实现
用户点一份黄焖鸡加鸡蛋和蔬菜
echo "-------------------欢迎使用--------------\n";
$rice = new Rice();
$egg = new Egg($rice);
$veg = new Veg($egg);
echo "菜品:";
print_r($veg -> getDesc());
echo "\n";
echo "单价:";
print_r($veg -> getPrice());
echo "\n";
echo "总计:";
print_r($veg -> cost());
echo "\n";
echo "------------------------------------------\n";
output:
-------------------欢迎使用--------------
菜品:黄焖鸡 + 鸡蛋 + 蔬菜
单价:黄焖鸡:20 + 鸡蛋:2 + 蔬菜:1.5
总计:23.5
------------------------------------------