الگوی Iterator – انجمن DEV

Summarize this content to 400 words in Persian Lang
Iterator Pattern چیست؟
الگوی Iterator یک الگوی رفتاری است که راهی برای دسترسی متوالی به عناصر یک شی انبوه (مجموعه) بدون افشای نمایش زیربنایی آن فراهم میکند.
چه زمانی از آن استفاده کنیم؟
زمانی که نمی خواهید ساختار داده مجموعه خود را آشکار کنید از الگوی Iterator استفاده کنید.
الگوی تکرار کننده کاربر زمانی که می خواهید یک رابط مشترک برای عبور از ساختارهای داده مختلف به جای داشتن بسیاری از کدهای پیمایش مشابه برای هر ساختار داده در برنامه خود.
مشکل
شرکت “Alpha Inc.” قرار است با Beta Inc. ادغام شود. ما در بخش منابع انسانی هستیم و باید داده های کارکنان آنها را با هم ادغام کنیم.EmployeeListA داده های کارکنان آلفا را نگه می دارد و EmployeeListB داده های کارکنان بتا را دارد. چون EmployeeListA از ساختار داده آرایه و EmployeeListB با استفاده از ArrayList، ما دو کد پیمایش می نویسیم.
public class HRDepartment {
public void printEmployee(){
EmployeeListA employeeListA = new EmployeeListA(“Alpha Inc”);
String[] alphaEmployee = employeeListA.getEmployees();
EmployeeListB employeeListB = new EmployeeListB(“Beta Inc”);
List betaEmployee = employeeListB.getEmployees();
// Traversal code for Array
for (int i = 0; i < alphaEmployee.length; i++) {
System.out.println(alphaEmployee[i] + ” from Alpha Inc.”);
}
// Traversal code for ArrayList
for (int i = 0; i < betaEmployee.size(); i++) {
System.out.println(betaEmployee.get(i) + ” from Beta Inc.”);
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
آیا می توانید مشکلات را تشخیص دهید؟ این مشکلی است که کد ما در حال حاضر دارد:
ما در حال کدنویسی برای اجرای دقیق هستیم (EmployeeListA و EmployeeListB) نه به یک رابط.
اگر ما تصمیم به تغییر EmployeeListA ساختار داده از آرایه به یکی دیگر مانند نقشه هش، ما باید خود را تغییر دهیم HRDepartment کلاس زیاد
HRDepartment نیاز به دانستن ساختار داخلی مجموعه دارد، به عبارت دیگر، ما در حال افشای ساختار داده مجموعه خود هستیم.
ما کدهای پیمایش را برای ساختار داده های مختلف، Array و ArrayList تکرار می کنیم.
راه حل
منطق تکرار را کپسوله کنید
پس از کجا شروع کنیم؟ بیایید کدهای تکرار تکراری خود را حذف کنیم.اگر بتوانیم منطق تکرار را کپسوله کنیم و یک رابط مشترک را معرفی کنیم، عالی خواهد بود HRDepartment می تواند فقط از یک رابط برای تکرار هر ساختار داده استفاده کند.
ما نیاز داریم Iterator رابط برای جدا کردن منطق تکرار از HRDepartment.
public interface Iterator {
boolean hasNext();
String next();
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
hasNext() مقدار بولی را برمی گرداند که نشان می دهد آیا یک مجموعه عنصر بعدی را دارد یا خیر. next() عنصر بعدی را در یک مجموعه برمی گرداند. (بعدا پیاده سازی واقعی را خواهید دید)
در EmployeeListA/EmployeeListA، حذف کردیم getEmployees() روش، زیرا ساختار داده انبوه ما را نشان می دهد. و مهمتر از همه، ما روش جدیدی نوشتیم createIterator() که یک Iterator بتن مربوطه را ایجاد می کند، برای مثال، EmployeeListA.createIterator() نمونه می کند EmployeeListAIterator.
معرفی رابط مشترک برای مصالح
بسیار خوب، ما اکنون منطق تکرار را کپسوله کردهایم، مجموعهای ما نمایش زیربنایی خود را نشان نمیدهند، کدهای پیمایش تکراری حذف شدهاند. اما هنوز یک مشکل باقی است، HRDepartment بستگی به سنگدانه های بتن دارد. بیایید یک رابط مشترک برای سنگدانه های بتن معرفی کنیم.
ساختار
پیاده سازی در جاوا
من حذف خواهم کرد EmployeeListBIterator و EmployeeListB's پیاده سازی به عنوان آنها شبیه به کسانی که از EmployeeListAIterator و EmployeeListA. اگر مطمئن نیستید که چگونه آنها را پیاده سازی کنید، می توانید در مخزن GitHub من بررسی کنید (لینک به مخزن من در انتهای این وبلاگ است).
public interface Iterator {
boolean hasNext();
String next();
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
public class EmployeeListAIterator implements Iterator {
private String[] employees;
private int index = 0;
public EmployeeListAIterator(String[] employees) {
this.employees = employees;
}
@Override
public boolean hasNext() {
if (index >= employees.length || employees[index] == null) {
return false;
}
return true;
}
@Override
public String next() {
String employee = employees[index];
index++;
return employee;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
public interface EmployeeList {
Iterator createIterator();
String getCompanyName();
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
public class EmployeeListA implements EmployeeList{
private String companyName;
private String[] employees;
private int SIZE = 5;
private int index = 0;
public EmployeeListA(String companyName) {
this.companyName = companyName;
employees = new String[SIZE];
addEmployee(“Alice”);
addEmployee(“Alisha”);
addEmployee(“Alex”);
}
public void addEmployee(String name) {
employees[index] = name;
index++;
}
public Iterator createIterator() {
return new EmployeeListAIterator(employees);
}
public String getCompanyName() {
return companyName;
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
public class HRDepartment {
EmployeeList listA;
EmployeeList listB;
public HRDepartment(EmployeeList listA, EmployeeList listB) {
this.listA = listA;
this.listB = listB;
}
public void printEmployee() {
Iterator listAIterator = listA.createIterator();
Iterator listBIterator = listB.createIterator();
System.out.println(“— Employees from ” + listA.getCompanyName() + ” —“);
printEmployee(listAIterator);
System.out.println(“— Employees from ” + listB.getCompanyName() + ” —“);
printEmployee(listBIterator);
}
private void printEmployee(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
خروجی:
— Employees from Alpha Inc —
Alice
Alisha
Alex
— Employees from Beta Inc —
Bob
Bella
Benjamin
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
دام
Iterator خود دلالت بر هیچ ترتیبی ندارد که در آن عناصر در طول تکرار بازدید میشوند. ترتیب تکرار به ساختار داده زیربنایی که در حال عبور است بستگی دارد، نه به Iterator.
Iterator از دسترسی به عناصر با نمایه پشتیبانی نمی کند.
رابط Iterator و Iterable در جاوا
قبل از پایان این وبلاگ، بیایید بررسی کنیم که چگونه می توانیم از آن استفاده کنیم java.util.Iterator.
تمام کلاسهای مجموعه مانند ArrayList، رابط مجموعه را پیادهسازی میکنند که رابط Iterable را گسترش میدهد. بنابراین هر کلاس مجموعه تکرارپذیر است.
public class IteratorDemo {
public static void main(String[] args) {
List nums = new ArrayList<>(List.of(0, 1, 2, 3));
Iterator iterator = nums.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در اینجا می توانید تمام پیاده سازی های الگوی طراحی را بررسی کنید.مخزن GitHub
Iterator Pattern چیست؟
الگوی Iterator یک الگوی رفتاری است که راهی برای دسترسی متوالی به عناصر یک شی انبوه (مجموعه) بدون افشای نمایش زیربنایی آن فراهم میکند.
چه زمانی از آن استفاده کنیم؟
- زمانی که نمی خواهید ساختار داده مجموعه خود را آشکار کنید از الگوی Iterator استفاده کنید.
- الگوی تکرار کننده کاربر زمانی که می خواهید یک رابط مشترک برای عبور از ساختارهای داده مختلف به جای داشتن بسیاری از کدهای پیمایش مشابه برای هر ساختار داده در برنامه خود.
مشکل
شرکت “Alpha Inc.” قرار است با Beta Inc. ادغام شود. ما در بخش منابع انسانی هستیم و باید داده های کارکنان آنها را با هم ادغام کنیم.EmployeeListA
داده های کارکنان آلفا را نگه می دارد و EmployeeListB
داده های کارکنان بتا را دارد. چون EmployeeListA
از ساختار داده آرایه و EmployeeListB
با استفاده از ArrayList، ما دو کد پیمایش می نویسیم.
public class HRDepartment {
public void printEmployee(){
EmployeeListA employeeListA = new EmployeeListA("Alpha Inc");
String[] alphaEmployee = employeeListA.getEmployees();
EmployeeListB employeeListB = new EmployeeListB("Beta Inc");
List betaEmployee = employeeListB.getEmployees();
// Traversal code for Array
for (int i = 0; i < alphaEmployee.length; i++) {
System.out.println(alphaEmployee[i] + " from Alpha Inc.");
}
// Traversal code for ArrayList
for (int i = 0; i < betaEmployee.size(); i++) {
System.out.println(betaEmployee.get(i) + " from Beta Inc.");
}
}
}
آیا می توانید مشکلات را تشخیص دهید؟ این مشکلی است که کد ما در حال حاضر دارد:
- ما در حال کدنویسی برای اجرای دقیق هستیم (
EmployeeListA
وEmployeeListB
) نه به یک رابط. - اگر ما تصمیم به تغییر
EmployeeListA
ساختار داده از آرایه به یکی دیگر مانند نقشه هش، ما باید خود را تغییر دهیمHRDepartment
کلاس زیاد -
HRDepartment
نیاز به دانستن ساختار داخلی مجموعه دارد، به عبارت دیگر، ما در حال افشای ساختار داده مجموعه خود هستیم. - ما کدهای پیمایش را برای ساختار داده های مختلف، Array و ArrayList تکرار می کنیم.
راه حل
منطق تکرار را کپسوله کنید
پس از کجا شروع کنیم؟ بیایید کدهای تکرار تکراری خود را حذف کنیم.
اگر بتوانیم منطق تکرار را کپسوله کنیم و یک رابط مشترک را معرفی کنیم، عالی خواهد بود HRDepartment
می تواند فقط از یک رابط برای تکرار هر ساختار داده استفاده کند.
ما نیاز داریم Iterator
رابط برای جدا کردن منطق تکرار از HRDepartment
.
public interface Iterator {
boolean hasNext();
String next();
}
hasNext()
مقدار بولی را برمی گرداند که نشان می دهد آیا یک مجموعه عنصر بعدی را دارد یا خیر. next()
عنصر بعدی را در یک مجموعه برمی گرداند. (بعدا پیاده سازی واقعی را خواهید دید)
در EmployeeListA
/EmployeeListA
، حذف کردیم getEmployees()
روش، زیرا ساختار داده انبوه ما را نشان می دهد. و مهمتر از همه، ما روش جدیدی نوشتیم createIterator()
که یک Iterator بتن مربوطه را ایجاد می کند، برای مثال، EmployeeListA.createIterator()
نمونه می کند EmployeeListAIterator
.
معرفی رابط مشترک برای مصالح
بسیار خوب، ما اکنون منطق تکرار را کپسوله کردهایم، مجموعهای ما نمایش زیربنایی خود را نشان نمیدهند، کدهای پیمایش تکراری حذف شدهاند. اما هنوز یک مشکل باقی است، HRDepartment
بستگی به سنگدانه های بتن دارد. بیایید یک رابط مشترک برای سنگدانه های بتن معرفی کنیم.
ساختار
پیاده سازی در جاوا
من حذف خواهم کرد EmployeeListBIterator
و EmployeeListB
's پیاده سازی به عنوان آنها شبیه به کسانی که از EmployeeListAIterator
و EmployeeListA
. اگر مطمئن نیستید که چگونه آنها را پیاده سازی کنید، می توانید در مخزن GitHub من بررسی کنید (لینک به مخزن من در انتهای این وبلاگ است).
public interface Iterator {
boolean hasNext();
String next();
}
public class EmployeeListAIterator implements Iterator {
private String[] employees;
private int index = 0;
public EmployeeListAIterator(String[] employees) {
this.employees = employees;
}
@Override
public boolean hasNext() {
if (index >= employees.length || employees[index] == null) {
return false;
}
return true;
}
@Override
public String next() {
String employee = employees[index];
index++;
return employee;
}
}
public interface EmployeeList {
Iterator createIterator();
String getCompanyName();
}
public class EmployeeListA implements EmployeeList{
private String companyName;
private String[] employees;
private int SIZE = 5;
private int index = 0;
public EmployeeListA(String companyName) {
this.companyName = companyName;
employees = new String[SIZE];
addEmployee("Alice");
addEmployee("Alisha");
addEmployee("Alex");
}
public void addEmployee(String name) {
employees[index] = name;
index++;
}
public Iterator createIterator() {
return new EmployeeListAIterator(employees);
}
public String getCompanyName() {
return companyName;
}
}
public class HRDepartment {
EmployeeList listA;
EmployeeList listB;
public HRDepartment(EmployeeList listA, EmployeeList listB) {
this.listA = listA;
this.listB = listB;
}
public void printEmployee() {
Iterator listAIterator = listA.createIterator();
Iterator listBIterator = listB.createIterator();
System.out.println("--- Employees from " + listA.getCompanyName() + " ---");
printEmployee(listAIterator);
System.out.println("--- Employees from " + listB.getCompanyName() + " ---");
printEmployee(listBIterator);
}
private void printEmployee(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
خروجی:
--- Employees from Alpha Inc ---
Alice
Alisha
Alex
--- Employees from Beta Inc ---
Bob
Bella
Benjamin
دام
- Iterator خود دلالت بر هیچ ترتیبی ندارد که در آن عناصر در طول تکرار بازدید میشوند. ترتیب تکرار به ساختار داده زیربنایی که در حال عبور است بستگی دارد، نه به Iterator.
- Iterator از دسترسی به عناصر با نمایه پشتیبانی نمی کند.
رابط Iterator و Iterable در جاوا
قبل از پایان این وبلاگ، بیایید بررسی کنیم که چگونه می توانیم از آن استفاده کنیم java.util.Iterator
.
تمام کلاسهای مجموعه مانند ArrayList، رابط مجموعه را پیادهسازی میکنند که رابط Iterable را گسترش میدهد. بنابراین هر کلاس مجموعه تکرارپذیر است.
public class IteratorDemo {
public static void main(String[] args) {
List nums = new ArrayList<>(List.of(0, 1, 2, 3));
Iterator iterator = nums.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
در اینجا می توانید تمام پیاده سازی های الگوی طراحی را بررسی کنید.
مخزن GitHub