أنماط التصميم المتقدمة في Java: من النظرية إلى الأمثلة المعقدة
أنماط التصميم هي حلول مجربة للمشكلات النمطية التي تنشأ أثناء تطوير البرمجيات. إذا كانت الأنماط الأساسية (Singleton, Factory, Observer) مألوفة لدى معظم مطوري Java، فإن الأنماط المتقدمة تتطلب فهماً عميقاً للهندسة المعمارية والقدرة على تطبيقها في سيناريوهات الأعمال المعقدة. في هذه المقالة، سنقوم بتحليل ثلاثة أنماط قوية: Visitor وCommand وState — مع أمثلة حقيقية بلغة Java ستساعدك على كتابة كود أكثر مرونة وقابلية للصيانة.
1. نمط Visitor: فصل الخوارزميات عن بنية البيانات
الغرض: يسمح بإضافة عمليات جديدة لكائنات من فئات مختلفة دون تغيير الفئات نفسها. مثالي للعمل مع التسلسلات الهرمية المعقدة حيث يلزم تنفيذ إجراءات مختلفة اعتماداً على نوع الكائن.
المشكلة: تخيل نظاماً لإدارة المستندات يحتوي على فئات TextDocument وImageDocument وSpreadsheetDocument. تحتاج إلى تنفيذ التصدير إلى PDF وHTML وTXT. بدون Visitor، كل تنسيق تصدير جديد سيتطلب تغيير جميع فئات المستندات.
الحل باستخدام Visitor:
// 1. واجهة العنصر (المستند)interface DocumentElement { void accept(DocumentVisitor visitor);}
// 2. العناصر المحددةclass TextDocument implements DocumentElement { private String content; public TextDocument(String content) { this.content = content; } public String getContent() { return content; } @Override public void accept(DocumentVisitor visitor) { visitor.visit(this); }}
class ImageDocument implements DocumentElement { private byte[] imageData; public ImageDocument(byte[] data) { this.imageData = data; } public byte[] getImageData() { return imageData; } @Override public void accept(DocumentVisitor visitor) { visitor.visit(this); }}
// 3. واجهة الزائرinterface DocumentVisitor { void visit(TextDocument doc); void visit(ImageDocument doc); void visit(SpreadsheetDocument doc);}
// 4. زائر محدد — التصدير إلى HTMLclass HtmlExporter implements DocumentVisitor { private StringBuilder sb = new StringBuilder(); @Override public void visit(TextDocument doc) { sb.append("<html><body><p>") .append(doc.getContent()) .append("</p></body></html>"); } @Override public void visit(ImageDocument doc) { sb.append("<html><body><img src='data:image/png;base64,") .append(Base64.getEncoder().encodeToString(doc.getImageData())) .append("'/></body></html>"); } @Override public void visit(SpreadsheetDocument doc) { sb.append("<html><body><table>...</table></body></html>"); } public String getResult() { return sb.toString(); }}
// 5. كود العميلpublic class DocumentSystem { public static void main(String[] args) { List<DocumentElement> documents = Arrays.asList( new TextDocument("Hello World"), new ImageDocument(new byte[]{1,2,3}) ); HtmlExporter exporter = new HtmlExporter(); for (DocumentElement doc : documents) { doc.accept(exporter); } System.out.println(exporter.getResult()); }}الميزة الرئيسية: لإضافة تنسيق جديد (مثل JSON)، يكفي إنشاء فئة جديدة JsonExporter implements DocumentVisitor — دون تغيير أي من فئات المستندات.