یک idiom ساده اما پر کاربرد برای پنهانسازی متدهای واسط در جاوا

یکی از اصول شئگرایی پنهانسازی حداکثری اطلاعات است (encapsulation). مدیریت کردن سطح دسترسی به متدها (methods) و کلاسها (classes) یکی از روشهای پنهانسازی اطلاعات است.
کد زیر را در نظر بگیرید:
import java.util.*;
public final class MyObserver implements Observer {
public void update(Observable o, Object arg) {
System.out.println(“MyObserver.update”);
System.out.println(“o = [“ + o + “], arg = [“ + arg + “]”);
}
public void register(Observable observable) {
observable.addObserver(this);
}
}
در این کد، کلاس MyObserver به صورت final تعریف شده است تا امکان تعریف زیرکلاس (subclass) برای این کلاس (class) وجود نداشته باشد، و بخشی از اطلاعات کلاس پنهان شوند.
با این وجود، با توجه به اینکه متد update در این کلاس سطح دسترسی public دارد(چون امضای متد update ارائهشده در واسط observer را پیادهسازی کرده است)، پنهانسازی اطلاعات به صورت کامل محقق نشده است.
حال سؤال این است که آیا روشی وجود دارد که این کلاس تابع update را پیادهسازی کند اما اطلاعات مربوط به پیادهسازی کلاس update پنهان شوند؟!
یکی از روشهایی که در [۱] ارائه شده است این است که کد فوق را مطابق با کد زیر اصلاح کنیم:
import java.util.*;
public final class MyObserverEncapsulated {
private final Observer observer = new Observer() {
public void update(Observable o, Object arg) {
MyObserverEncapsulated.this.update(o, arg);
}
};
private void update(Observable o, Object arg) {
System.out.println(“MyObserver.update”);
System.out.println(“o = [“ + o + “], arg = [“ + arg + “]”);
}
public void register(Observable observable) {
observable.addObserver(observer);
}
}
همانگونه که مشاهده میشود، در این کد یک anonymous class در داخل کلاس MyObserverEncapsulated تعریف شده است که سطح دسترسی آن private است. در واقع، کلاس MyObserverEncapsulated پیادهسازی واسط را به کلاس داخلی محول کرده است؛ کلاس داخلی که سطح دسترسی آن private است و دسترسی به متد update را محدود میکند.
final تعریف کردن کلاس MyObserverEncapsulated نیز کمک میکند تا امکان دسترسی به instance ای از شئِ observer از طریق override کردن متد register وجود نداشته باشد.البته اگر یک شئ جعلی از نوع observable برای متد register فرستاده شود، این امکان وجود دارد که این instance از شئِ observable از طریق instance ای از شئِ observer دسترسی به متد update را فراهم کند (اگرچه متد upadate با سطح دسترسی private تعریف شده است).
در جاوا ۸ میتوان با استفاده از LambdaExpressions کد فوق را با تعداد کمتری از خطوط کد پیادهسازی کرد:
import java.util.*;
public final class MyObserverLambda {
private final Observer observer = (o, arg) -> update(o, arg);
private void update(Observable o, Object arg) {
System.out.println(“MyObserver.update”);
System.out.println(“o = [“ + o + “], arg = [“ + arg + “]”);
}
public void register(Observable observable) {
observable.addObserver(observer);
}
}
منبع:
[۱] http://www.javaspecialists.eu