3.10. Visitor¶
3.10.1. تعریف¶
دیزاین پترن Visitor یک الگوی رفتاری محسوب میشه که اجازه میده الگوریتم ها رو از آبجکت هایی که اون ها رو مدیریت می کنن جدا کنیم.
این ساختار به ما اجازه میده operation های جدیدی رو به کلاس مورد نظرمون بدون تغییر ساختارش اضافه کنیم.
3.10.2. چه زمانی استفاده میشه؟¶
این الگو رو معمولا زمانی استفاده می کنیم که قصد داریم عملیاتی رو روی تمام المان های یک آبجکت با ساختار پیچیده اجرا کنیم.
همچنین این الگو رو زمانی استفاده می کنیم که یک رفتار مشخص فقط در بعضی کلاس های یک سلسله مراتب معنا میده.
3.10.3. اجزاء¶
الگوی طراحی Visitor از چند بخش اصلی تشکیل میشه:
اولین قسمت Visitor هست که یک interface یا abstract هست که یک سری متد در اون تعریف میشه که هر کدوم مربوط به یک سری المان های متفاوت از ساختار آبجکت هستن.
بخش Visitor عملیاتی رو مشخص می کنه که میتونه روی تمام المان های ساختار آبجکت بدون توجه به پیاده سازی اون اعمال بشه.
بخش بعد Concrete Visitor ها هستن که کلاس هایی هستن که Visitor رو پیاده سازی می کنن و و هر کدوم پیاده سازی خاص خودشون از Visitor رو دارن و میتونن عملیات مورد نظر رو روی المان و داده های اون اجرا کنن.
بخش بعد Element هست که میشه interface یا abstract ای که متد accept در اون تعریف میشه. این متد Visitor رو به عنوان پارامتر دریافت می کنه و به Visitor اجازه میده به داده های المان دسترسی پیدا کنه و عملیات مورد نظرش رو انجام بده.
بخش بعد هم پیاده سازی های Element ها هستن که هر کدوم پیاده سازی خاصی از accept رو دارن و با توجه به المان مورد نظر، متد Visitor مناسب رو فراخوانی می کنن.
From Wikipedia, the free encyclopedia
Caution
✅ مزایای استفاده
رعایت اصل Open/Closed از اصول Solid
رعایت اصل تک مسئولیتی
Warning
❌ معایب استفاده
بعد از اینکه یک کلاس اضافه یا حذف شد باید تمام visitor ها آپدیت بشن
3.10.4. کاربرد عملی¶
این الگو در زبان PHP بسیار کم کاربرد محسوب میشه و سعی می کنم خیلی تمرکز نکنیم روی این الگو یا دیزاین پترن.
اما به هر حال به عنوان نمونه میتونیم یک مثال عملی از این الگو داشته باشیم.
تصور کنید اشکال مختلفی مثل دایره و مربع و مستطیل داریم و قصد داریم مساحت و محیط هر کدوم رو محاسبه کنیم.
میریم سراغ دیزاین پترن Visitor
3.10.5. پیاده سازی¶
ساختار ShapeInterface رو ابتدا تعریف می کنیم:
1<?php
2
3// Define the Shape interface
4interface Shape
5{
6 public function accept(ShapeVisitorInterface $visitor);
7}
بعد پیاده سازی های مختلفش رو داریم:
1<?php
2
3// Define the Circle class
4class Circle implements Shape
5{
6 private $radius;
7
8 public function __construct($radius)
9 {
10 $this->radius = $radius;
11 }
12
13 public function accept(ShapeVisitorInterface $visitor)
14 {
15 $visitor->visitCircle($this);
16 }
17
18 public function getRadius()
19 {
20 return $this->radius;
21 }
22}
23
24// Define the Square class
25class Square implements Shape
26{
27 private $length;
28
29 public function __construct($length)
30 {
31 $this->length = $length;
32 }
33
34 public function accept(ShapeVisitorInterface $visitor)
35 {
36 $visitor->visitSquare($this);
37 }
38
39 public function getLength()
40 {
41 return $this->length;
42 }
43}
44
45// Define the Rectangle class
46class Rectangle implements Shape
47{
48 private $width;
49 private $height;
50
51 public function __construct($width, $height)
52 {
53 $this->width = $width;
54 $this->height = $height;
55 }
56
57 public function accept(ShapeVisitorInterface $visitor)
58 {
59 $visitor->visitRectangle($this);
60 }
61
62 public function getWidth()
63 {
64 return $this->width;
65 }
66
67 public function getHeight()
68 {
69 return $this->height;
70 }
71}
بریم سراغ ساختار ShapeVisitorInterface
1<?php
2
3// Define the ShapeVisitor interface
4interface ShapeVisitorInterface
5{
6 public function visitCircle(Circle $circle);
7
8 public function visitSquare(Square $square);
9
10 public function visitRectangle(Rectangle $rectangle);
11}
که به این صورت پیاده سازی میشه:
1<?php
2
3// Define the ShapeVisitor class
4class ShapeVisitor implements ShapeVisitorInterface
5{
6 private $area;
7 private $perimeter;
8
9 public function visitCircle(Circle $circle)
10 {
11 $this->area = pi() * $circle->getRadius() * $circle->getRadius();
12 $this->perimeter = 2 * pi() * $circle->getRadius();
13 }
14
15 public function visitSquare(Square $square)
16 {
17 $this->area = $square->getLength() * $square->getLength();
18 $this->perimeter = 4 * $square->getLength();
19 }
20
21 public function visitRectangle(Rectangle $rectangle)
22 {
23 $this->area = $rectangle->getWidth() * $rectangle->getHeight();
24 $this->perimeter = 2 * ($rectangle->getWidth() + $rectangle->getHeight());
25 }
26
27 public function getArea()
28 {
29 return $this->area;
30 }
31
32 public function getPerimeter()
33 {
34 return $this->perimeter;
35 }
36}
3.10.6. نحوه فراخوانی¶
1<?php
2
3// Example usage
4$shapes = [
5 new Circle(5),
6 new Square(4),
7 new Rectangle(3, 6),
8];
9
10// Create a new instance of the ShapeVisitor class
11$visitor = new ShapeVisitor();
12
13// Loop through each shape and call its accept() method, passing in the visitor object
14foreach ($shapes as $shape) {
15 $shape->accept($visitor);
16
17 echo get_class($shape) . " area is: " . $visitor->getArea() . ", perimeter is: " . $visitor->getPerimeter() . "\n";
18}
و تمام!