منهج التكرار في لغة البرمجة جافا

نمط تصميم المكرر في واحد من أنماط السلوك. يُستخدم نمط المكرر لتوفير طريقة قياسية للتجوال من خلال مجموعة من الكائنات. يُستخدم نمط المكرر على نطاق واسع في إطار جمع Java. واجهة المكرر توفر طرقًا للتجوال من خلال مجموعة.

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

وفقًا لـ GoF ، فإن نية نمط تصميم المكرر هي:

توفير وسيلة للوصول إلى عناصر كائن مجمع بدون الكشف عن تمثيله الأساسي.

نمط المكرر ليس مقتصرًا فقط على التجوال من خلال مجموعة ، بل يمكننا توفير أنواع مختلفة من المكررات بناءً على متطلباتنا. يخفي نمط تصميم المكرر التنفيذ الفعلي للتجوال من خلال المجموعة ويستخدم برامج العميل فقط طرق المكرر.

مثال على نمط المكرر

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

package com.journaldev.design.iterator;

public enum ChannelTypeEnum {

	ENGLISH, HINDI, FRENCH, ALL;
}

ChannelTypeEnum هو تعبير شخصي جافا يحدد جميع أنواع القنوات المختلفة. Channel.java

package com.journaldev.design.iterator;

public class Channel {

	private double frequency;
	private ChannelTypeEnum TYPE;
	
	public Channel(double freq, ChannelTypeEnum type){
		this.frequency=freq;
		this.TYPE=type;
	}

	public double getFrequency() {
		return frequency;
	}

	public ChannelTypeEnum getTYPE() {
		return TYPE;
	}
	
	@Override
	public String toString(){
		return "Frequency="+this.frequency+", Type="+this.TYPE;
	}
	
}

Channel هو صنف POJO بسيط يحتوي على السمات التردد ونوع القناة. ChannelCollection.java

package com.journaldev.design.iterator;

public interface ChannelCollection {

	public void addChannel(Channel c);
	
	public void removeChannel(Channel c);
	
	public ChannelIterator iterator(ChannelTypeEnum type);
	
}

واجهة ChannelCollection تعرّف العقد لتنفيذ فئة مجموعتنا. لاحظ أن هناك طرقًا لإضافة وإزالة قناة ولكن لا يوجد طريقة تعيد قائمة القنوات. تحتوي واجهة ChannelCollection على طريقة تعيد محدد التجوال. واجهة ChannelIterator تعرّف الطرق التالية؛ ChannelIterator.java

package com.journaldev.design.iterator;

public interface ChannelIterator {

	public boolean hasNext();
	
	public Channel next();
}

الآن واجهتنا الرئيسية والفئات الأساسية جاهزة، دعونا نقم بتنفيذ فئة المجموعة ومحدد التجوال. ChannelCollectionImpl.java

package com.journaldev.design.iterator;

import java.util.ArrayList;
import java.util.List;

public class ChannelCollectionImpl implements ChannelCollection {

	private List<Channel> channelsList;

	public ChannelCollectionImpl() {
		channelsList = new ArrayList<>();
	}

	public void addChannel(Channel c) {
		this.channelsList.add(c);
	}

	public void removeChannel(Channel c) {
		this.channelsList.remove(c);
	}

	@Override
	public ChannelIterator iterator(ChannelTypeEnum type) {
		return new ChannelIteratorImpl(type, this.channelsList);
	}

	private class ChannelIteratorImpl implements ChannelIterator {

		private ChannelTypeEnum type;
		private List<Channel> channels;
		private int position;

		public ChannelIteratorImpl(ChannelTypeEnum ty,
				List<Channel> channelsList) {
			this.type = ty;
			this.channels = channelsList;
		}

		@Override
		public boolean hasNext() {
			while (position < channels.size()) {
				Channel c = channels.get(position);
				if (c.getTYPE().equals(type) || type.equals(ChannelTypeEnum.ALL)) {
					return true;
				} else
					position++;
			}
			return false;
		}

		@Override
		public Channel next() {
			Channel c = channels.get(position);
			position++;
			return c;
		}

	}
}

لاحظ تنفيذ الفئة الداخلية فئة داخلية لواجهة محدد التجوال بحيث لا يمكن استخدام التنفيذ من قبل أي مجموعة أخرى. يتبع نفس النهج أيضًا من قبل فئات المجموعة وتحتوي جميعها على تنفيذ فئة داخلية لواجهة التنفيذ. دعونا نكتب برنامج اختبار بسيط لنستخدم مجموعتنا ومحدد التجوال للتجوال عبر مجموعة القنوات. IteratorPatternTest.java

package com.journaldev.design.iterator;

public class IteratorPatternTest {

	public static void main(String[] args) {
		ChannelCollection channels = populateChannels();
		ChannelIterator baseIterator = channels.iterator(ChannelTypeEnum.ALL);
		while (baseIterator.hasNext()) {
			Channel c = baseIterator.next();
			System.out.println(c.toString());
		}
		System.out.println("******");
		// نوع محدد القناة
		ChannelIterator englishIterator = channels.iterator(ChannelTypeEnum.ENGLISH);
		while (englishIterator.hasNext()) {
			Channel c = englishIterator.next();
			System.out.println(c.toString());
		}
	}

	private static ChannelCollection populateChannels() {
		ChannelCollection channels = new ChannelCollectionImpl();
		channels.addChannel(new Channel(98.5, ChannelTypeEnum.ENGLISH));
		channels.addChannel(new Channel(99.5, ChannelTypeEnum.HINDI));
		channels.addChannel(new Channel(100.5, ChannelTypeEnum.FRENCH));
		channels.addChannel(new Channel(101.5, ChannelTypeEnum.ENGLISH));
		channels.addChannel(new Channel(102.5, ChannelTypeEnum.HINDI));
		channels.addChannel(new Channel(103.5, ChannelTypeEnum.FRENCH));
		channels.addChannel(new Channel(104.5, ChannelTypeEnum.ENGLISH));
		channels.addChannel(new Channel(105.5, ChannelTypeEnum.HINDI));
		channels.addChannel(new Channel(106.5, ChannelTypeEnum.FRENCH));
		return channels;
	}

}

عند تشغيل البرنامج أعلاه، ينتج الناتج التالي;

Frequency=98.5, Type=ENGLISH
Frequency=99.5, Type=HINDI
Frequency=100.5, Type=FRENCH
Frequency=101.5, Type=ENGLISH
Frequency=102.5, Type=HINDI
Frequency=103.5, Type=FRENCH
Frequency=104.5, Type=ENGLISH
Frequency=105.5, Type=HINDI
Frequency=106.5, Type=FRENCH
******
Frequency=98.5, Type=ENGLISH
Frequency=101.5, Type=ENGLISH
Frequency=104.5, Type=ENGLISH

نقاط مهمة حول نمط التنفيذ

  • نمط التنفيذ مفيد عندما ترغب في توفير وسيلة قياسية للتجوال عبر مجموعة وإخفاء منطق التنفيذ عن برنامج العميل.
  • المنطق للتكرار مضمن في المجموعة نفسها ويساعد البرنامج العميل على تكرارها بسهولة.

نمط تصميم Iterator في JDK

نحن جميعًا نعلم أن مجموعة Collection Iterator هي أفضل مثال على تنفيذ نمط التكرار ولكن هل تعلم أن فئة java.util.Scanner أيضًا تنفذ واجهة Iterator. اقرأ هذه المقالة لتتعلم عن فئة Java Scanner. هذا كل شيء بخصوص نمط تصميم Iterator، أتمنى أن يكون مفيدًا وسهل الفهم.

Source:
https://www.digitalocean.com/community/tutorials/iterator-design-pattern-java