Dependency Injection with Spring.Net p4
Posted On Thursday, May 22, 2008 at at 4:47 PM by Unknown(Bài viết dịch từ bài Dependency Injection with Spring.Net của David Consdorf, thêm hành thêm tiêu rồi nấu lại bởi Nguyễn Thoại )
- Trong phần 3, tôi đã sử dụng một ví dụ khác với các ví dụ truyền thống để giải thích mẫu thiết kế Strategy Pattern. Nếu bạn muốn tìm hiểu thêm những ví dụ khác, các bạn có thể tham khảo bài viết của tác giả Dadiv Consdorf ở đây hoặc trên wiki. Như đã nói ở bài viết trước, mẫu thiết kế Strategy Pattern sẽ giúp bạn trừu tượng hóa (abstract) những xử lý (behavior) tương tự nhau của đổi tượng(object) bằng cách đưa những xử lý đó ra những lớp độc lập, và những lớp này sẽ cùng implement một interface.
- Ở những ví dụ truyền thống, các bài viết thường sử dụng bài toán về các thuật toán sắp xếp để minh hoạ mẫu thiết kế Strategy. Trong đó, một lớp NumberArray sẽ có khả năng sắp xếp danh sách các số bằng nhiều thuật toán khác nhau. Các thuật toán này sẽ được đóng gói trong các lớp Sort và chính những lớp BubbleSort, HeapSort,… này lại implement cùng 1 interface ISortStrategy. Lớp NumberArray không sử dụng một thuật toán cụ thể nào để sắp xếp, nó sẽ giữ một object thuộc về kiểu ISortStrategy và các thuật toán sort sẽ được chuyển đổi dễ dàng trong lúc chương trình chạy và ngoài ra nếu sử dụng Spring.NET ta có thể thay đổi những lớp Strategy bằng file config.
- Quay lại ví dụ ở bài trước, các bạn sẽ thấy sự tương tự. Nếu xem lớp “ThuBayTuanToi” là chương trình chính thì các bạn sẽ thấy lớp NguyenThoai có thể chọn cách DiXemPhim hoặc DiAnToi một cách dễ dàng bằng cách khởi tạo với một đối tượng thuộc kiểu tương ứng. Tuy nhiên, việc này sẽ làm mất đi tính loose coupling của chương trình vì lớp “NguyenThoai” phải reference đến những lớp DiXemPhim, DiAnToi. Nói cách khác nó phải biết DiXemPhim là như thế nào, DiAnToi là như thế nào. Spring.NET sẽ giúp tôi giải quyết vấn đề đó, Spring.NET sẽ giữ tất cả những chiến thuật đi chơi của tôi, và NguyenThoai với Spring.NET chỉ cần thoả thuận với nhau các kí hiệu : “ĐiĂn”, “XemPhim”, “Cafe”,... Bản thỏa thuận như sau:
<object name="DiAnToi" type="DiAnToi, __Code" singleton="true">
</object>
<object name="DiXemPhim" type="DiXemPhim, __Code" singleton="true">
</object>
<object name="DiUongCafe" type="DiUongCafe, __Code" singleton="true">
</object>
<object name="XemPhim" type="NguyenThoai, __Code" singleton="false">
<constructor-arg name="cachDiChoi" ref="DiXemPhim" />
</object>
<object name="DiAnToi" type="NguyenThoai, __Code" singleton="false">
<constructor-arg name="cachDiChoi" ref="DiAnToi" />
</object>
<object name="Cafe" type="NguyenThoai, __Code" singleton="false">
<constructor-arg name="cachDiChoi" ref="DiUongCafe" />
</object>
Hình 8: Mapping các objects trong file config.
- Như vậy ít nhất tôi với Spring.NET đã thoả thuận với nhau 3 mật hiệu, nếu cần đi chơi theo cách nào thì thôi chỉ nói cho Spring.NET biết mật hiệu và Spring sẽ lấy ra những thứ tôi cần. Cách làm như trên giúp chúng ta thay đổi các chiến thuật cần sử dụng trong lúc runtime. Còn việc map đối tượng chính với các lớp cài đặt các behavior đã được định nghĩa trong file config như hình 8. Trong phần 5 của loạt bài này, chúng ta sẽ nói thêm một ví dụ nữa về ứng dụng Spring.NET để map các đối tượng với nhau. Còn bây giờ, chúng ta hãy xem tôi sẽ sử dụng Spring như thế nào trong lần đi chơi thứ bảy tuần tới :
public class ThuBayTuanToi {
public void main() {
IApplicationContext ctx = ContextRegistry.GetContext()
NguyenThoai _thoai = (NguyenThoai)ctx.GetObject("XemPhim");
_thoai.Money = 100.000 VND;
_thoai.Vehicle = new Vehicle("Xe Bus");
_thoai.DanBanGaiDiChoi();
}
}
Hình 9: Sử dụng Spring.NET để lấy đối tượng được map.
- Một điều quan trọng nữa nên nói đến là việc sử dụng mẫu thiết kế Singleton bên trong Spring.NET. Bạn có thấy rằng ở những ví dụ trước đều có một property là singleton ở phần object mapping trong các file config. Theo tôi, Singleton là mẫu thiết kế đơn giản nhất, thông dụng nhất và thường được sử dụng nhất. Để hiểu rõ hơn về thiết kế này, các bạn hãy xem sơ đồ lớp bên dưới:
Hình 10: Sơ đồ lớp của mẫu Singleton.
- Theo hình thì chúng ta thấy lớp singleton có một hàm GetInstance() để trả về instance của object Singleton. Tuy nhiên tôi thích cách sử dụng Public Property hơn :
public class Singleton {
private static Singleton _instance = null;
protected Singleton() {
}
public static Singleton Instance
{
get
{
if ( _instance == null )
_instance = new Singleton();
return _instance;
}
}
}
Hình 11: Ví dụ mẫu Singleton.
- Mẫu thiết kế singleton giúp chúng ta bảo đảm rằng lúc nào cũng tồn tại nhiều nhất 1 instance của một lớp tương ứng. Như các bạn thấy trong sơ đồ lớp, chúng ta sẽ làm được chuyện đó bằng cách thiết kế một lớp với 1 protected constructor (hàm khởi tạo), và vì là protected nên nó chỉ có thể tạo ra instance bên trong. Chúng ta nên sử dung protected ở đây mà không dung private vì khi khai báo là protected chúng ta có thể sử dụng unit test để test và những lớp con có thể kế thừa constructor này. Với cách làm như vậy, không một chỗ nào trong chương trình có thể tạo ra instance của lớp. Do đó, sẽ chỉ có 1 instance duy nhất của đối tượng được tạo ra và đối tượng đó sẽ tồn tại trong xuốt quá trình chạy của chương trình.
- Lớp singleton sẽ phải cung cấp một public static Property hoặc một hàm static với kiểu trả về là chính lớp đó để các đối tượng khác có thể truy xuất được object mà nó đóng gói bên trong. Mấu thiết kế này có vẻ như rất giống với cách chúng ta sử dụng những hàm static, nhưng nó khác biệt ở chỗ singleton cho chúng ta sự linh động hơn trong lập trình vì chúng ta vẫn có một instance thực sự của một đối tượng để làm việc. Ngoài ra có một số điểm khác biệt khác mà tôi sẽ đề cập đến trong bài viết khác. Việc áp dụng mẫu singleton đúng chỗ đúng lúc trong ứng dụng rất có lợi, chương trình của bạn sẽ chạy nhanh hơn vì không cần phải liên tục tạo ra những đối tượng mới và cũng không cần huỷ những đối tượng sau khi đã sử dụng xong. Ngoài ra cũng sẽ tiết kiệm được bộ nhớ của máy tính vì không cần phải lưu trữ nhiều đối tượng trong hệ thống. Ngày nay, lợi ích thứ hai này không thể hiện rõ vì bộ nhớ máy tính của chúng ta không ngừng được tăng lên với giá ngày càng rẻ, nhưng theo tôi tối ưu hoá ứng dụng khi có thể là không bao giờ thừa nhất là khi chúng ta áp dụng design pattern
- Spring.NET đã sử dụng nguyên tắc này của mẫu singleton bằng cách cho phép người dùng quyết định xem 1 lớp có duy nhất một instance hay không. Vì vậy, trong ví dụ trên, lớp NguyenThoai không cần phải là singleton, bởi vì sao? Bởi vì thường thì tình hình tài chính và tâm trạng tôi hoàn toàn khác nhau ở mỗi ngày thứ 7. Tôi sẽ có nhiều lần đi chơi khác nhau và với mỗi lần ấy có thể tôi sẽ có số tiền khác nhau. Ngoài ra tôi là một người rất chung thuỷ, tôi thích đến những chỗ cũ, ăn ở những quán ăn cũ nên theo tôi những lớp DiAnToi, DiXemPhim, … nên là những lớp singleton. Ngoài nhiệm vụ thực hiện quá trình đi chơi và biến IsHappy của tôi thành true thì nó chẳng nên có vai trò gì khác. Tương tự, ở ví dụ của tác giả với những thuật toán sort, những lớp BubleSort, HeapSort, QuickSort,... cũng nên là singleton vì ngoài chuyện sắp xếp một mảng các số, nó chẳng cần giữ giá trị sau khi sắp xếp của mảng làm gì. Do đó mình chỉ cần khởi tạo một lần và sử dụng suốt cho những lần sau.
- Hi vọng kết thúc phần 4 này, các bạn có thể hiểu được đôi chút về Spring.NET, hiểu được Spring có thể giúp các bạn làm gì và vì sao nên làm như vậy. Nói chung khi thiết kế lớp cho chương trình, nếu bạn gặp phải tình huống một lớp A có giữ 1 instance của lớp B thì bạn đang đối mặt với tính loose coupling. Lúc đấy, bạn nên nghĩ xem sau này có khi nào cần phải làm một lớp B2 tương tự lớp B hay không. Nêú có, chính là lúc bạn cần nghĩ đến Dependency Injection và Spring là một trong những lựa chọn để giải quyết bài toán của bạn. Để giúp bạn hiểu rõ hơn về khả năng mapping objects của Spring, ở phần 5, tác giả sẽ nói đến một ví dụ khác lý thú hơn, thông dụng và thực tế hơn trong việc áp dụng Spring.NET để kết nối các đối tượng với nhau.
(Các bạn đang xem phần 4)
ủng hộ http://www.onlaa.com/ nhé
http://www.dofactory.com/Patterns/PatternSingleton.aspx#_self1
Có code và ví dụ khá dễ hiểu
mất hình rồi, bạn cập nhật lại được không