ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 示例 ### 概念示例 **使用示例:** 访问者模式在 PHP 代码中不太常用,因为它不仅复杂,应用范围也比较狭窄。 <details> <summary>main.php</summary> ``` <?php interface Visitor { public function visitConcreteComponentA(ConcreteComponentA $element): void; public function visitConcreteComponentB(ConcreteComponentB $element): void; } interface Component { public function accept(Visitor $visitor): void; } class ConcreteComponentA implements Component { public function accept(Visitor $visitor): void { $visitor->visitConcreteComponentA($this); } public function exclusiveMethodOfConcreteComponentA(): string { return "A"; } } class ConcreteComponentB implements Component { public function accept(Visitor $visitor): void { $visitor->visitConcreteComponentB($this); } public function specialMethodOfConcreteComponentB(): string { return "B"; } } class ConcreteVisitor1 implements Visitor { public function visitConcreteComponentA(ConcreteComponentA $element): void { echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor1\n"; } public function visitConcreteComponentB(ConcreteComponentB $element): void { echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor1\n"; } } class ConcreteVisitor2 implements Visitor { public function visitConcreteComponentA(ConcreteComponentA $element): void { echo $element->exclusiveMethodOfConcreteComponentA() . " + ConcreteVisitor2\n"; } public function visitConcreteComponentB(ConcreteComponentB $element): void { echo $element->specialMethodOfConcreteComponentB() . " + ConcreteVisitor2\n"; } } function clientCode(array $components, Visitor $visitor) { // ... foreach ($components as $component) { $component->accept($visitor); } // ... } $components = [ new ConcreteComponentA(), new ConcreteComponentB(), ]; echo "The client code works with all visitors via the base Visitor interface:\n"; $visitor1 = new ConcreteVisitor1(); clientCode($components, $visitor1); echo "\n"; echo "It allows the same client code to work with different types of visitors:\n"; $visitor2 = new ConcreteVisitor2(); clientCode($components, $visitor2); ``` </details> <br /> 输出 ``` The client code works with all visitors via the base Visitor interface: A + ConcreteVisitor1 B + ConcreteVisitor1 It allows the same client code to work with different types of visitors: A + ConcreteVisitor2 B + ConcreteVisitor2 ``` ### 公司报表 <details> <summary>main.php</summary> ``` <?php interface Entity { public function accept(Visitor $visitor): string; } // 公司 class Company implements Entity { private $name; /** * @var Department[] */ private $departments; public function __construct(string $name, array $departments) { $this->name = $name; $this->departments = $departments; } public function getName(): string { return $this->name; } public function getDepartments(): array { return $this->departments; } // ... public function accept(Visitor $visitor): string { return $visitor->visitCompany($this); } } // 部门 class Department implements Entity { private $name; /** * @var Employee[] */ private $employees; public function __construct(string $name, array $employees) { $this->name = $name; $this->employees = $employees; } public function getName(): string { return $this->name; } public function getEmployees(): array { return $this->employees; } public function getCost(): int { $cost = 0; foreach ($this->employees as $employee) { $cost += $employee->getSalary(); } return $cost; } // ... public function accept(Visitor $visitor): string { return $visitor->visitDepartment($this); } } // 雇员 class Employee implements Entity { private $name; private $position; private $salary; public function __construct(string $name, string $position, int $salary) { $this->name = $name; $this->position = $position; $this->salary = $salary; } public function getName(): string { return $this->name; } public function getPosition(): string { return $this->position; } public function getSalary(): int { return $this->salary; } // ... public function accept(Visitor $visitor): string { return $visitor->visitEmployee($this); } } interface Visitor { public function visitCompany(Company $company): string; public function visitDepartment(Department $department): string; public function visitEmployee(Employee $employee): string; } class SalaryReport implements Visitor { public function visitCompany(Company $company): string { $output = ""; $total = 0; foreach ($company->getDepartments() as $department) { $total += $department->getCost(); $output .= "\n--" . $this->visitDepartment($department); } $output = $company->getName() . " (" . money_format("%i", $total) . ")\n" . $output; return $output; } public function visitDepartment(Department $department): string { $output = ""; foreach ($department->getEmployees() as $employee) { $output .= " " . $this->visitEmployee($employee); } $output = $department->getName() . " (" . money_format("%i", $department->getCost()) . ")\n\n" . $output; return $output; } public function visitEmployee(Employee $employee): string { return money_format("%#6n", $employee->getSalary()) . " " . $employee->getName() . " (" . $employee->getPosition() . ")\n"; } } // 包含雇员的部门 $mobileDev = new Department("Mobile Development", [ new Employee("Albert Falmore", "designer", 100000), new Employee("Ali Halabay", "programmer", 100000), new Employee("Sarah Konor", "programmer", 90000), new Employee("Monica Ronaldino", "QA engineer", 31000), new Employee("James Smith", "QA engineer", 30000), ]); // 包含雇员的部门 $techSupport = new Department("Tech Support", [ new Employee("Larry Ulbrecht", "supervisor", 70000), new Employee("Elton Pale", "operator", 30000), new Employee("Rajeet Kumar", "operator", 30000), new Employee("John Burnovsky", "operator", 34000), new Employee("Sergey Korolev", "operator", 35000), ]); // 包含部门的公寓 $company = new Company("SuperStarDevelopment", [$mobileDev, $techSupport]); setlocale(LC_MONETARY, 'en_US'); $report = new SalaryReport(); echo "Client: I can print a report for a whole company:\n\n"; echo $company->accept($report); echo "\nClient: ...or just for a single department:\n\n"; echo $techSupport->accept($report); // $export = new JSONExport(); // echo $company->accept($export); ``` </details> <br /> 输出 ``` Client: I can print a report for a whole company: SuperStarDevelopment (USD550,000.00) --Mobile Development (USD351,000.00) $100,000.00 Albert Falmore (designer) $100,000.00 Ali Halabay (programmer) $ 90,000.00 Sarah Konor (programmer) $ 31,000.00 Monica Ronaldino (QA engineer) $ 30,000.00 James Smith (QA engineer) --Tech Support (USD199,000.00) $ 70,000.00 Larry Ulbrecht (supervisor) $ 30,000.00 Elton Pale (operator) $ 30,000.00 Rajeet Kumar (operator) $ 34,000.00 John Burnovsky (operator) $ 35,000.00 Sergey Korolev (operator) Client: ...or just for a single department: Tech Support (USD199,000.00) $ 70,000.00 Larry Ulbrecht (supervisor) $ 30,000.00 Elton Pale (operator) $ 30,000.00 Rajeet Kumar (operator) $ 34,000.00 John Burnovsky (operator) $ 35,000.00 Sergey Korolev (operator) ```