当一个对象或者数据有多种展示方式的时候用装饰者模式. 比如数组可以以json, xml的展示方式. 再比如用户数据A页面会有一种展示方式. B页面会有一种展示方式
数组装饰
现在来用装饰者模式展示array. 先定义一个对象用来接受数组和输出输出.
class OutputData {
private DecoratorInterface $decorator;
public function __construct(private array $data) {}
public function setDecorator(DecoratorInterface $decorator) {
$this->decorator = $decorator;
}
public function output() {
return $this->decorator->renderData($this->data);
}
}
定义装饰者, 分别定义JSON和XML
interface DecoratorInterface {
public function renderData($data);
}
class XMLRender implements DecoratorInterface {
function toXml(SimpleXMLElement $object, array $data) {
foreach ($data as $key => $value) {
// if the key is an integer, it needs text with it to actually work.
$valid_key = is_numeric($key) ? "key_$key" : $key;
$new_object = $object->addChild(
$valid_key,
is_array($value) ? null : htmlspecialchars($value)
);
if (is_array($value)) {
$this->toXml($new_object, $value);
}
}
}
public function renderData($data) {
$xml = new SimpleXMLElement('<root/>');
$this->toXml($xml, $data);
return $xml->saveXML();
}
}
class JsonRender implements DecoratorInterface {
public function renderData($data) {
return json_encode($data);
}
}
最后根据所需输出指定类型
$data = new OutputArray([
'books' => [
'Abook',
'Bbook',
'Cbook'
],
'cart' => [
'Acart',
'Bcart',
'Ccart'
]
]);
$data->setDecorator(new XMLRender());
$data->setDecorator(new JsonRender());
print_r($data->output());
商品装饰
定义菜品接口
interface FoodItem {
// 定义附加的成本.
public function cost();
}
// 定义一个手抓饼. 成本为10块钱.
class HandCake implements FoodItem {
private array $items = [];
public function cost() {
return 10;
}
public function addItem(FoodItem $item) {
$this->items[] = $item;
}
public function Calculation() {
$total = $this->cost();
foreach ($this->items as $item) {
$total += $item->cost();
}
return $total;
}
}
定义小菜可选增加
// 定义鸡蛋小菜的成品为4块
class Egg implements FoodItem {
public function cost () {
return 4;
}
}
// 定义一个火腿价格为6块
class Ham implements FoodItem {
public function cost () {
return 6;
}
}
$handcake = new HandCake();
$handcake->addItem(new Egg());
$handcake->addItem(new Egg());
$handcake->addItem(new Egg());
$handcake->addItem(new Ham());
$handcake->addItem(new Ham());
print $handcake->Calculation();
产品活动装饰
定义一个商品类
class Product {
public string $title;
public float $price;
}
定义活动接口
interface ProductActivities {
public function getReduce(Product $product);
}
定义活动
// 双十一减5块.
class Two11 implements ProductActivities {
public function getReduce($product) {
return 5;
}
}
// 满500减50.
class Filled500 implements ProductActivities {
public function getReduce(Product $product) {
if ($product->price > 500) {
return 50;
}
}
}
定义产品建造者来获取产品
class ProductBuilder {
private Product $product;
private array $activities;
public function __construct($title, $price) {
$product = new Product();
$product->title = $title;
$product->price = $price;
$this->product = $product;
}
/**
* 获取商品.
*
* @return mixed
*/
public function getProduct() {
// 根据活动重新计算减少的价格.
$price = $this->product->price;
foreach ($this->activities as $activity) {
$price -= (int)$activity->getReduce($this->product);
}
$this->product->price = $price;
return $this->product;
}
/**
* 添加活动.
*
* @param $activity
*/
public function addActivity($activity) {
$this->activities[] = $activity;
}
}
最后测试
$product = new ProductBuilder('Iphone16', '9000');
$product->addActivity(new Two11());
$product->addActivity(new Filled500());
print_r($product->getProduct());