در این قسمت تیم کدگیت را با آموزش Visitor پترن در جاوا همراهی کنید. در ابتدای این جلسه Visitor پترن را توضیح داده سپس دیاگرامی کلی از آن را معرفی میکنیم. در آخر یک مثال از دنیای واقعی را پیاده سازی خواهیم کرد. همچنین پیشنهاد میکنیم قبل از مطالعه این جلسه، آموزشهای زیر را بررسی کنید:
Behavioral Design Pattern
یکی از زیر شاخههای دیزاین پترن Behavioral Design Pattern میباشد. یکی از وظایف اصلی این دیزاین پترن، تعامل اشیا و جداسازی وظایف آنها با یکدیگر است. تعریف کامل Behavioral Design Pattern بدین صورت است که، تمامی اشیا با یکدیگر به راحتی بتوانند ارتباط برقرار کرده، بدون آنکه باعث وابستگی بین آنها شود.
Visitor پترن
Visitor پترن وقتی استفاده میشود که ما عملیاتی یکسان را بین چندین شی انجام میدهیم. با استفاده از این پترن میتوان عملیات منطقی ( Operational Behavior ) برنامه را در کلاسی دیگر انجام داد. این کاری است که این پترن انجام میدهد.
مثالی که در مورد این پترن میتوان زد خرید در فروشگاهها است. یک خریدار مجموعهای از اجناس مختلف را خریداری کرده و به صندوق مراجعه میکند. صندوق دار بعضی اجناس را جدا میکند (بعضی ها نیاز به کشیدن وزن دارند مانند حبوبات یا …). و در آخر مجموع قیمت توسط صندوق دار محاسبه میگردد. برای درک بهتر موضوع ما این مثال را پیاده سازی میکنیم.
مثال Visitor پترن در جاوا
فرض میکنیم ما دو آیتم کتاب و میوه را داریم. یک صندوق دار برای دریافت آیتم ها و یک مشتری برای خرید داریم. کلاسهای Book و Fruit برای آیتمهای ما پیاده سازی شده و یک کلاس Visitor برای دریافت آیتمها بوده، کلاس Client نیز برای مشتری پیاده سازی شده است. در تصویر بالا میتوانید دیاگرام این مثال را ببینید. کد این مثال به صورت زیر است:
public interface ItemElement {
public int accept(ShoppingCartVisitor visitor);
}
public class Book implements ItemElement {
private int price;
private String isbnNumber;
public Book(int cost, String isbn) {
this.price = cost;
this.isbnNumber = isbn;
}
public int getPrice() {
return price;
}
public String getIsbnNumber() {
return isbnNumber;
}
@Override
public int accept(ShoppingCartVisitor visitor) {
return visitor.visit(this);
}
}
public class Fruit implements ItemElement {
private int pricePerKg;
private int weight;
private String name;
public Fruit(int priceKg, int wt, String nm) {
this.pricePerKg = priceKg;
this.weight = wt;
this.name = nm;
}
public int getPricePerKg() {
return pricePerKg;
}
public int getWeight() {
return weight;
}
public String getName() {
return this.name;
}
@Override
public int accept(ShoppingCartVisitor visitor) {
return visitor.visit(this);
}
}
public interface ShoppingCartVisitor {
int visit(Book book);
int visit(Fruit fruit);
}
public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {
@Override
public int visit(Book book) {
int cost = 0;
// apply 5$ discount if book price is greater than 50
if (book.getPrice() > 50) {
cost = book.getPrice() - 5;
} else
cost = book.getPrice();
System.out.println("Book ISBN::" + book.getIsbnNumber() + " cost ="
+ cost);
return cost;
}
@Override
public int visit(Fruit fruit) {
int cost = fruit.getPricePerKg() * fruit.getWeight();
System.out.println(fruit.getName() + " cost = " + cost);
return cost;
}
}
تست Visitor پترن در جاوا
برای تست کدهای بالا، کد Main زیر را بزنید:
public class ShoppingCartClient {
public static void main(String[] args) {
ItemElement[] items = new ItemElement[] { new Book(20, "1234"),
new Book(100, "5678"), new Fruit(10, 2, "Banana"),
new Fruit(5, 5, "Apple") };
int total = calculatePrice(items);
System.out.println("Total Cost = " + total);
}
private static int calculatePrice(ItemElement[] items) {
ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
int sum = 0;
for (ItemElement item : items) {
sum = sum + item.accept(visitor);
}
return sum;
}
}
خروجی کد بالا به صورت زیر میباشد:
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160