در این قسمت تیم کدگیت را با آموزش Interpreter پترن در جاوا همراهی کنید. در ابتدای این آموزش Interpreter Pattern را معرفی میکنیم. سپس با توجه به نوع استفاده این پترن، یک مثال واقعی از آن خواهیم زد. پیش نیاز این آموزش شامل موارد زیر میباشد:
Behavioral Design Pattern
یکی از زیر شاخههای دیزاین پترن Behavioral Design Pattern میباشد. یکی از وظایف اصلی این دیزاین پترن، تعامل اشیا و جداسازی وظایف آنها با یکدیگر است. تعریف کامل Behavioral Design Pattern بدین صورت است که، تمامی اشیا با یکدیگر به راحتی بتوانند ارتباط برقرار کرده، بدون آنکه باعث وابستگی بین آنها شود.
Interpreter پترن در جاوا
Interpreter به معنای مترجم است. در دیزاین پترن، Interpreter را به عنوان نمایشی برای گرامر یک زبان در نظر میگیرند. اما تعریف مذکور کمی گیجکننده است. بهتر است ابتدا معنای گرامر را بدانیم:
دستور زبان یا گرامر مجموعه قوانین و ضوابط حاکم بر ساختار واژهها، جملهها، واجها و آواها و معناها در زبان است(ویکیپدیا).
گرامر را مجموعهای از قوانین میدانند و دقیقا این تعریف در دیزاین پترن پیاده سازی میشود. Interpreter پترن در جاوا از مجموعهای قوانین تشکیل شده که بر اساس آن قوانین، یک خروجی (در دستور زبان معنی جمله و در شی گرایی میتوان True یا False باشد) تولید میشود. برای درک بهتر این پترن مثال زیر را بخوانید.
مثال Interpreter پترن در جاوا
در مثال Interpreter پترن در جاوا میخواهیم And و Or منطقی را بر روی جملات یک زبان بنویسیم. قوانین برنامه ما And و Or بوده پس گرامر هستند. دیاگرام زیر این پترن را به صورت کامل نشان میدهد:
یک Interface به نام Expression داریم که سه کلاس TerminalExpression، OrExpression و AndExpression آن را Implement میکنند. کلاس TerminalExpression یک کلمه از زبان را ذخیره میکند دو کلاس دیگر نقش گرامر را برای کلمات ذخیره شده، دارند. قبل از توضیحات بیشتر کد کلاسهای بالا را ببینید:
public interface Expression {
public boolean interpret(String context);
}
public class AndExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
public class OrExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpret(String context) {
if (context.contains(data)) {
return true;
}
return false;
}
}
در کلاس TerminalExpression یک String ذخیره میکنیم. متد interpret بررسی میکند قوانینی که تعیین کردهایم درست است یا خیر؟ اگر درست بود True وگرنه False برمیگرداند.
تست مثال Interpreter پترن در جاوا
برای تست کدهای بالا، کد Main زیر را بزنید:
public class InterpreterPatternDemo {
// Rule: Robert and John are male
public static Expression getMaleExpression() {
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}
// Rule: Julie is a married women
public static Expression getMarriedWomanExpression() {
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}
public static void main(String[] args) {
Expression isMale = getMaleExpression();
Expression isMarriedWoman = getMarriedWomanExpression();
System.out.println("John is male? " + isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
}
}
در کد بالا دو متد برای نوشتن Rule نوشته و از متد Main، آنها را صدا کردهایم. متدهای getMaleExpression و getMarriedWomanExpression برای نوشتن Rule های ما است. در آخر اگر متد Interpret هر کدام را صدا کنیم با توجه به گرامری که نوشتهایم (And و Or) متد، True یا False برمیگرداند. خروجی برنامه به صورت زیر میباشد:
John is male? true
Julie is a married women? true