mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-14 20:17:21 +00:00
75 files changed
+6204
No files matched your search
@@ -0,0 +1,167 @@
|
||||
---
|
||||
title: Acyclic Visitor
|
||||
shortTitle: Acyclic Visitor
|
||||
category: Behavioral
|
||||
language: ar
|
||||
tag:
|
||||
- Extensibility
|
||||
---
|
||||
## الهدف
|
||||
|
||||
السماح بإضافة وظائف جديدة إلى تسلسلات الفئات الموجودة دون التأثير عليها، ودون إنشاء الدوائر المعتمدة المزعجة التي هي جزء من نمط GoF (Gang of Four) للزائر (Visitor).
|
||||
|
||||
## التوضيح
|
||||
|
||||
مثال من العالم الحقيقي
|
||||
|
||||
> لدينا تسلسل فئات مودم. يجب أن تتم زيارة المودمات في هذه التسلسلات بواسطة خوارزمية خارجية بناءً على بعض الفلاتر (هل المودم متوافق مع Unix أو DOS؟).
|
||||
|
||||
بصيغة أخرى
|
||||
|
||||
> يتيح نمط Acyclic Visitor إضافة وظائف إلى تسلسلات الفئات الموجودة دون تعديلها.
|
||||
|
||||
[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) يقول
|
||||
|
||||
> يسمح نمط Acyclic Visitor بإضافة وظائف جديدة إلى تسلسلات الفئات الموجودة دون التأثير عليها، ودون إنشاء الدوائر المعتمدة التي هي جزء من نمط الزائر (Visitor Pattern) في GangOfFour.
|
||||
|
||||
**مثال برمجي**
|
||||
|
||||
هنا لدينا تسلسل `Modem`.
|
||||
|
||||
|
||||
```java
|
||||
public abstract class Modem {
|
||||
public abstract void accept(ModemVisitor modemVisitor);
|
||||
}
|
||||
|
||||
public class Zoom extends Modem {
|
||||
...
|
||||
@Override
|
||||
public void accept(ModemVisitor modemVisitor) {
|
||||
if (modemVisitor instanceof ZoomVisitor) {
|
||||
((ZoomVisitor) modemVisitor).visit(this);
|
||||
} else {
|
||||
LOGGER.info("Only ZoomVisitor is allowed to visit Zoom modem");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Hayes extends Modem {
|
||||
...
|
||||
@Override
|
||||
public void accept(ModemVisitor modemVisitor) {
|
||||
if (modemVisitor instanceof HayesVisitor) {
|
||||
((HayesVisitor) modemVisitor).visit(this);
|
||||
} else {
|
||||
LOGGER.info("Only HayesVisitor is allowed to visit Hayes modem");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
بعد ذلك، لدينا تسلسل `ModemVisitor`.
|
||||
|
||||
|
||||
```java
|
||||
public interface ModemVisitor {
|
||||
}
|
||||
|
||||
public interface HayesVisitor extends ModemVisitor {
|
||||
void visit(Hayes hayes);
|
||||
}
|
||||
|
||||
public interface ZoomVisitor extends ModemVisitor {
|
||||
void visit(Zoom zoom);
|
||||
}
|
||||
|
||||
public interface AllModemVisitor extends ZoomVisitor, HayesVisitor {
|
||||
}
|
||||
|
||||
public class ConfigureForDosVisitor implements AllModemVisitor {
|
||||
...
|
||||
@Override
|
||||
public void visit(Hayes hayes) {
|
||||
LOGGER.info(hayes + " used with Dos configurator.");
|
||||
}
|
||||
@Override
|
||||
public void visit(Zoom zoom) {
|
||||
LOGGER.info(zoom + " used with Dos configurator.");
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigureForUnixVisitor implements ZoomVisitor {
|
||||
...
|
||||
@Override
|
||||
public void visit(Zoom zoom) {
|
||||
LOGGER.info(zoom + " used with Unix configurator.");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
وأخيرًا، هنا "الزوار" في العمل.
|
||||
|
||||
|
||||
```java
|
||||
var conUnix = new ConfigureForUnixVisitor();
|
||||
var conDos = new ConfigureForDosVisitor();
|
||||
var zoom = new Zoom();
|
||||
var hayes = new Hayes();
|
||||
hayes.accept(conDos);
|
||||
zoom.accept(conDos);
|
||||
hayes.accept(conUnix);
|
||||
zoom.accept(conUnix);
|
||||
```
|
||||
|
||||
ناتج البرنامج:
|
||||
|
||||
|
||||
```
|
||||
// Hayes modem used with Dos configurator.
|
||||
// Zoom modem used with Dos configurator.
|
||||
// Only HayesVisitor is allowed to visit Hayes modem
|
||||
// Zoom modem used with Unix configurator.
|
||||
```
|
||||
|
||||
|
||||
## مخطط الفئات
|
||||
|
||||

|
||||
|
||||
## التطبيق
|
||||
|
||||
يمكن استخدام هذا النمط في الحالات التالية:
|
||||
|
||||
* عندما تحتاج إلى إضافة وظيفة جديدة إلى تسلسل فئات دون التأثير عليها أو تعديلها.
|
||||
* عندما توجد وظائف تعمل على التسلسل ولكنها لا تنتمي إلى التسلسل بحد ذاته. على سبيل المثال، الفئات `ConfigureForDOS` و `ConfigureForUnix` و `ConfigureForX`.
|
||||
* عندما تحتاج إلى تنفيذ عمليات مختلفة تمامًا على كائن اعتمادًا على نوعه.
|
||||
* عندما يكون من المتوقع توسيع التسلسل الزائر بشكل متكرر باستخدام مشتقات من فئة العنصر.
|
||||
* عندما يكون عملية إعادة التجميع، الربط، الاختبار أو توزيع المشتقات من فئة العنصر مرهقة جدًا.
|
||||
|
||||
## الدروس التعليمية
|
||||
|
||||
* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)
|
||||
|
||||
## العواقب
|
||||
|
||||
الجوانب الجيدة:
|
||||
|
||||
* لا توجد دوائر اعتماد بين التسلسلات.
|
||||
* لا حاجة لإعادة تجميع جميع الزوار إذا تم إضافة زائر جديد.
|
||||
* لا يسبب أخطاء في الترجمة في الزوار الموجودين إذا كانت التسلسل تحتوي على عضو جديد.
|
||||
|
||||
الجوانب السيئة:
|
||||
|
||||
|
||||
* ينتهك [مبدأ الاستبدال في ليسكوف](https://java-design-patterns.com/principles/#liskov-substitution-principle) من خلال إظهار أنه يمكن قبول جميع الزوار مع الاهتمام بزائر واحد فقط.
|
||||
* يجب إنشاء تسلسل زوار موازٍ لجميع الأعضاء في التسلسل الذي يمكن زيارته.
|
||||
|
||||
## الأنماط المتعلقة
|
||||
|
||||
* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)
|
||||
|
||||
|
||||
## الحقوق
|
||||
|
||||
|
||||
* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)
|
||||
* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
Reference in new issue
Block a user