مثال على نمط تصميم الديكور في Java

نمط التصميم الديكوري يستخدم لتعديل وظيفة كائن ما أثناء التشغيل. في الوقت نفسه، لن تتأثر الحالات الأخرى من نفس الصنف بهذا، لذلك يحصل الكائن الفردي على السلوك المعدل. نمط التصميم الديكوري هو أحد أنماط التصميم الهيكلي (مثل نمط التكيف، نمط الجسر، نمط المكون) ويستخدم الفصول الفنية الأو المعرفات النموذجية مع التركيب للتنفيذ.

نمط التصميم الديكوري

نستخدم التوريث أو التكوين لتمديد سلوك كائن ما ولكن هذا يتم في وقت الترجمة وهو قابل للتطبيق على جميع الحالات من الصنف. لا يمكننا إضافة أي وظيفة جديدة أو إزالة أي سلوك موجود في وقت التشغيل – هذا حين يدخل نمط الديكور في الصورة. لنفترض أننا نريد تنفيذ أنواع مختلفة من السيارات – يمكننا إنشاء واجهة Car لتعريف طريقة assemble ثم يمكننا أن نمتلك سيارة أساسية، ويمكننا أن نمتد ذلك إلى سيارة رياضية وسيارة فاخرة. ستبدو الهرمة التنفيذية كما في الصورة أدناه. ولكن إذا أردنا الحصول على سيارة في وقت التشغيل تحتوي على ميزات كل من سيارة رياضية وسيارة فاخرة، فإن التنفيذ يصبح معقدًا وإذا أردنا تحديد أي ميزات يجب أن تضاف أولاً، فإن الأمر يصبح أكثر تعقيدًا. الآن تخيل إذا كان لدينا عشرة أنواع مختلفة من السيارات، فإن منطق التنفيذ باستخدام التوريث والتكوين سيكون من المستحيل إدارته. لحل هذا النوع من الوضع البرمجي، نطبق نمط الديكور في جافا. نحتاج إلى وجود الأنواع التالية لتنفيذ نمط تصميم الديكور.

  1. واجهة المكون – الواجهة أو الفئة المجردة التي تعرف الطرق التي سيتم تنفيذها. في حالتنا ستكون Car واجهة المكون.

    package com.journaldev.design.decorator;
    
    public interface Car {
    
    	public void assemble();
    }
    
  2. تنفيذ المكون – التنفيذ الأساسي لواجهة المكون. يمكننا أن نمتلك فئة BasicCar كتنفيذ للمكون.

    package com.journaldev.design.decorator;
    
    public class BasicCar implements Car {
    
    	@Override
    	public void assemble() {
    		System.out.print("Basic Car.");
    	}
    
    }
    
  3. المزين – تقوم فئة المزين بتنفيذ واجهة المكون ولديها علاقة HAS-A مع واجهة المكون. يجب أن يكون من الممكن الوصول إلى متغير المكون من قبل فئات المزين الفرعية، لذا سنقوم بجعل هذا المتغير محميًا.

    package com.journaldev.design.decorator;
    
    public class CarDecorator implements Car {
    
    	protected Car car;
    	
    	public CarDecorator(Car c){
    		this.car=c;
    	}
    	
    	@Override
    	public void assemble() {
    		this.car.assemble();
    	}
    
    }
    
  4. مزينات محددة – توسيع وظائف المزين الأساسي وتعديل سلوك المكون وفقًا لذلك. يمكننا أن نمتلك فئات مزينة محددة كـ LuxuryCar و SportsCar.

    package com.journaldev.design.decorator;
    
    public class SportsCar extends CarDecorator {
    
    	public SportsCar(Car c) {
    		super(c);
    	}
    
    	@Override
    	public void assemble(){
    		super.assemble();
    		System.out.print(" إضافة ميزات سيارة رياضية.");
    	}
    }
    
    package com.journaldev.design.decorator;
    
    public class LuxuryCar extends CarDecorator {
    
    	public LuxuryCar(Car c) {
    		super(c);
    	}
    	
    	@Override
    	public void assemble(){
    		super.assemble();
    		System.out.print(" إضافة ميزات سيارة فاخرة.");
    	}
    }
    

نمط تصميم المزين – مخطط الصفوف

برنامج اختبار نمط تصميم المزين

package com.journaldev.design.test;

import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;

public class DecoratorPatternTest {

	public static void main(String[] args) {
		Car sportsCar = new SportsCar(new BasicCar());
		sportsCar.assemble();
		System.out.println("\n*****");
		
		Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
		sportsLuxuryCar.assemble();
	}

}

لاحظ أن برنامج العميل يمكنه إنشاء أنواع مختلفة من الكائنات في وقت التشغيل ويمكنهم أيضًا تحديد ترتيب التنفيذ. مخرجات البرنامج الاختباري أعلاه هي:

Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.

نمط تصميم المزين – نقاط مهمة

  • نمط تصميم المزين مفيد في توفير قدرات التعديل أثناء التشغيل وبالتالي أكثر مرونة. من السهل الحفاظ عليه وتوسيعه عندما يكون عدد الخيارات أكبر.
  • عيب نمط تصميم المزين هو أنه يستخدم الكثير من الكائنات من نفس النوع (المزينين).
  • نمط المزيّن يستخدم كثيرًا في فئات Java IO، مثل FileReader، BufferedReader وما إلى ذلك.

Source:
https://www.digitalocean.com/community/tutorials/decorator-design-pattern-in-java-example