Saturday, March 5, 2011

Tự xây dựng 1 framework đảo ngược điều khiển (IoC - Inversion of Control)

1. Nguyên lý đảo ngược điều khiển
Sự ra đời của Spring như là một chọn lựa khác cho EJB đã đánh dấu một bước ngoặt trong lịch sử phát triển của Enterprise Java. Theo thời gian Spring không ngừng được mở rộng với ngày càng nhiều tính năng mới. Tuy vậy, một trong những phần chủ chốt của Spring vẫn là IoC container. Đảo ngược điều khiển là một nguyên lý (hay design pattern) có từ trước khi Spring ra đời năm 2002. Nguyên lý này cũng được mô tả trong cuốn sách Design Pattern của Gang of Four với cách nói nhại theo Hollywood: "Don't call us. We'll call you"

Vậy đảo ngược điều khiển là gì? Hãy xét ví dụ sau:
Giả sử ta có interface Animal với phương thức là say() với ngụ ý là  mỗi loài vật sẽ có tiếng kêu khác nhau. Ví dụ bò rống ò ò ò, còn chó thì sủa gâu gâu gâu.


public interface Animal {
void say();
}
public class Cow implements Animal {
public void say() {
System.out.println("Cow say: oo oo oo");
}
}

public class Dog implements Animal {
public void say() {
System.out.println("Dog say: gau gau gau");
}
}

Theo cách truyền thống để tạo một đối tượng ta cần phải dùng lệnh như sau:

Animal animal = new Dog();
animal.say();

Cách làm này có nhược điểm là nếu muốn thay đổi kiểu của animal là Cow thì cần phải viết lại code. 

2. Tự xây dựng 1 framework đảo ngược điều khiển:
Để xây dựng một framework đảo ngược điều khiển, ta dùng Java Reflection để khởi tạo đối tượng động. Trước tiên ta cần đọc file cấu hình để lấy ra thông tin về tên lớp hiện thực cần được dùng. Giả sử ta có file ioc.properties nội dung như sau:

package.name = examples
bean.name = Animal
implementation.name = Cow

Ta có interface Animal và các lớp hiện thực Cow và Dog như mô tả ở phần 1.

Lớp Injector được hiện thực như sau:

public class Injector {

static Animal getInstance(String propertiesFile) throws FileNotFoundException, IOException, InstantiationException, IllegalAccessException, ClassNotFoundException
{
Animal dependency = null;
Properties pros = new Properties();
pros.load(new FileInputStream(propertiesFile));
String packageName = pros.getProperty("package.name");
String beanName = pros.getProperty("bean.name");
String implementationName = pros.getProperty("implementation.name");

dependency = (Animal)Class.forName(packageName+"."+implementationName).newInstance();
return dependency;
}
}

Cài đặt hàm main để test:
public static void main(String[] args) throws FileNotFoundException, IOException, InstantiationException, IllegalAccessException, ClassNotFoundException
{
Properties p = System.getProperties();
String classpath = p.getProperty("java.class.path");
Animal animal = Injector.getInstance(classpath+"/examples/ioc.properties");
animal.say();
}

Chạy thử ta được kết quả như sau:
Cow say: oo oo oo

Download source code ví dụ này tại đây: MyIOC.zip - 6.0 KB





1 comment: