ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 示例 ### 概念模式 <details> <summary>main.php</summary> ``` <?php abstract class Component { /** * @var Component */ protected $parent; public function setParent(Component $parent) { $this->parent = $parent; } public function getParent(): Component { return $this->parent; } public function add(Component $component): void { } public function remove(Component $component): void { } public function isComposite(): bool { return false; } abstract public function operation(): string; } class Leaf extends Component { public function operation(): string { return "Leaf"; } } class Composite extends Component { /** * @var \SplObjectStorage */ protected $children; public function __construct() { $this->children = new \SplObjectStorage(); } public function add(Component $component): void { $this->children->attach($component); $component->setParent($this); } public function remove(Component $component): void { $this->children->detach($component); $component->setParent(null); } public function isComposite(): bool { return true; } public function operation(): string { $results = []; foreach ($this->children as $child) { $results[] = $child->operation(); } return "Branch(" . implode("+", $results) . ")"; } } function clientCode(Component $component) { // ... echo "RESULT: " . $component->operation(); // ... } $simple = new Leaf(); clientCode($simple); echo "\n\n"; $branch1 = new Composite(); $branch1->add(new Leaf()); $branch1->add(new Leaf()); $branch2 = new Composite(); $branch2->add(new Leaf()); $tree = new Composite(); $tree->add($branch1); $tree->add($branch2); clientCode($tree); echo "\n\n"; function clientCode2(Component $component1, Component $component2) { // ... if ($component1->isComposite()) { $component1->add($component2); } echo "RESULT: " . $component1->operation(); // ... } clientCode2($tree, $simple); ``` </details> <br /> 输出 ``` RESULT: Leaf RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)) RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)% ``` ### 生成 form 元素 <details> <summary>main.php</summary> ``` <?php namespace RefactoringGuru\Composite\RealWorld; abstract class FormElement { protected $name; protected $title; protected $data; public function __construct(string $name, string $title) { $this->name = $name; $this->title = $title; } public function getName(): string { return $this->name; } public function setData($data): void { $this->data = $data; } public function getData(): array { return $this->data; } abstract public function render(): string; } class Input extends FormElement { private $type; public function __construct(string $name, string $title, string $type) { parent::__construct($name, $title); $this->type = $type; } public function render(): string { return "<label for=\"{$this->name}\">{$this->title}</label>\n" . "<input name=\"{$this->name}\" type=\"{$this->type}\" value=\"{$this->data}\">\n"; } } abstract class FieldComposite extends FormElement { /** * @var FormElement[] */ protected $fields = []; public function add(FormElement $field): void { $name = $field->getName(); $this->fields[$name] = $field; } public function remove(FormElement $component): void { $this->fields = array_filter($this->fields, function ($child) use ($component) { return $child != $component; }); } /** * @param array $data */ public function setData($data): void { foreach ($this->fields as $name => $field) { if (isset($data[$name])) { $field->setData($data[$name]); } } } public function getData(): array { $data = []; foreach ($this->fields as $name => $field) { $data[$name] = $field->getData(); } return $data; } public function render(): string { $output = ""; foreach ($this->fields as $name => $field) { $output .= $field->render(); } return $output; } } class Fieldset extends FieldComposite { public function render(): string { $output = parent::render(); return "<fieldset><legend>{$this->title}</legend>\n$output</fieldset>\n"; } } class Form extends FieldComposite { protected $url; public function __construct(string $name, string $title, string $url) { parent::__construct($name, $title); $this->url = $url; } public function render(): string { $output = parent::render(); return "<form action=\"{$this->url}\">\n<h3>{$this->title}</h3>\n$output</form>\n"; } } function getProductForm(): FormElement { $form = new Form('product', "Add product", "/product/add"); $form->add(new Input('name', "Name", 'text')); $form->add(new Input('description', "Description", 'text')); $picture = new Fieldset('photo', "Product photo"); $picture->add(new Input('caption', "Caption", 'text')); $picture->add(new Input('image', "Image", 'file')); $form->add($picture); return $form; } function loadProductData(FormElement $form) { $data = [ 'name' => 'Apple MacBook', 'description' => 'A decent laptop.', 'photo' => [ 'caption' => 'Front photo.', 'image' => 'photo1.png', ], ]; $form->setData($data); } function renderProduct(FormElement $form) { // .. echo $form->render(); // .. } $form = getProductForm(); loadProductData($form); renderProduct($form); ``` </details> <br /> 输出 ``` <form action="/product/add"> <h3>Add product</h3> <label for="name">Name</label> <input name="name" type="text" value="Apple MacBook"> <label for="description">Description</label> <input name="description" type="text" value="A decent laptop."> <fieldset> <legend>Product photo</legend> <label for="caption">Caption</label> <input name="caption" type="text" value="Front photo."> <label for="image">Image</label> <input name="image" type="file" value="photo1.png"> </fieldset> </form> ```