Showing posts with label Adapter Pattern. Show all posts
Showing posts with label Adapter Pattern. Show all posts

Sử dụng Adapter Pattern Trong Lập Trình Hướng Đối Tượng

Adapter Pattern Samble In Real Life

I/ Giới thiệu.

- Khái niệm Adapter đã xuất hiện từ rất lâu và được sử dụng rất nhiều trong cuộc sống. Thiết bị điện tử của bạn không thể sạc pin bằng điện 220V mà phải thông qua một bộ chuyển, biến điện 220 thành 12V. Bạn có một con chuột với Jack cắm USB nhưng máy đã hết chỗ cắm, người bán tặng bạn thêm 1 bộ chuyển từ USB sang PS2 để giải quyết vấn đề trên…Đó là những ví dụ hay gặp nhất về Adapter, và vì chúng quá thông dụng nên ít ai ngờ đến cái mình đang sử dụng hằng ngày lại là một kiểu adapter nào đó. Từ lâu, khái niệm Adapter đã được 4 đại ca về Design Pattern đưa vào lĩnh vực làm phần mềm và nó tỏ ra có ích không kém. Tôi dám chắc là các bạn ai đều cũng từng sử dụng đến Adapter trong cuộc sống của mình, thế thì tại sao lại không sử dụng nó trong lập trình để giải quyết những vấn đề tương tự:bbpskien: :

Adapter Pattern Samble In Real Life
Adapter Pattern Samble In Real Life

Adapter Pattern Samble In Real Life
Adapter Pattern Samble In Real Life


- Inheritance là một trong 3 nguyên tắc cơ bản của lập trình hướng đối tượng. Khi cần xây dựng một lớp dựa trên một hoặc nhiều lớp hay interface có sẵn bạn chỉ cần khai báo lớp mới kế thừa lớp cũ và có thể viết thêm những method, attribute của mình tùy thích. Tuy nhiên sẽ có lúc tính kế thừa của OOP sẽ không sử dụng được. Thật sự là có nhiều trường hợp như vậy mà tôi đã từng gặp phải. Giả sử bạn cần mở rộng một lớp nhưng lớp đó là lớp seal (không cho kế thừa) thì inheritance chắc chắn không sử dụng được rồi. Một ví dụ khác là khi bạn cần kết hợp nhiều thứ có sẵn để làm ra một lớp mới sử dụng lại những thứ đó. Như các bạn biết C# và Java không hỗ trợ đa kế thừa, chúng ta không thể nào kế thừa từ 2 lớp có sẵn được. Như vậy nếu bạn đã có một lớp để tìm ước số chung lớn nhất của hai số tự nhiên, một lớp để cộng hai phân số, và khi dùng adapter để kết hợp hai thứ có sẵn đó bạn sẽ làm được một lớp có khả năng cộng hai phân số với nhau với kết quả phép cộng là phân số đã tối giản.:bbpnen:

- Như vậy, Adapter Pattern là một design pattern, nó còn được gọi là Wrapper Pattern biến đổi một lớp không thể sử dụng trực tiếp được thành một lớp mới có thể sử dụng. Trong một số trường hợp, Adapter Pattern còn được sử dụng để biến đổi dạng dữ liệu. Để tiết kiệm chỗ trong và giảm tính phức tạp trong database, nhiều giá trị string có thể được lưu thành một string duy nhất với kí tự phân cách đặc biệt, mẫu Adapter sẽ chịu trách nhiệm tách các string đó ra thành array để nơi khác có thể sử dụng. Nhưng nói chung Adapter Pattern được sử dụng đúng nhất khi biến cái không thể thành cái có thể.:bbpraroi:

II/ Sử dụng Adapter Pattern như thế nào?

- Theo tôi nói ở trên, Adapter Pattern thường được dùng để biến cái không thể thành cái có thể, biến lớp không thể sử dụng thành một lớp mới có thể sử dụng. Tuy nhiên, Adapter Pattern còn được dùng để biến những lớp có sẵn thành một thứ khác dễ và tiện sử dụng hơn. Vì vậy có hai cách thiết kế và áp dụng Adapter Pattern trong lập trình, ở một số tài liệu Design Pattern, hai cách này được gọi là Object Adapter Pattern và Class Adapter Pattern. Một số trang còn gọi là Inheritance-Way và Composition-Way. Nói chung những cách gọi này đều dựa trên cách thiết kế lớp Adapter. Object Adapter Pattern hay Composition-Way là cách sử dụng một đối tượng thuộc về lớp chúng ta muốn biến đổi bên trong lớp Adapter. Trong khi đó, ClassAdapterPattern hay Inheritance-Way là cách kế thừa từ lớp chúng ta muốn biến đổi hoặc mở rộng thêm.

III/ Ví dụ mẫu về Adapter Pattern

- Tôi sẽ lần lượt đưa 2 ví dụ thiết kế lớp về 2 cách này:

A. Object Adapter Pattern (Composition-Way)

- Để kiếm đủ tiền ăn nhậu, massage:bbpxtay:, ngoài giờ làm ở cty tôi nhận làm thêm một ứng dụng quản lý bán hàng, trong đó có hỗ trợ lập biểu đồ thể hiện doanh số các kiểu. Hiện tại tôi đã đạo được phần code vẽ biểu đồ cột của một tên sinh viên học cùng trường. Tiếc thay search mãi thì chỉ tìm được một thư viện vẽ biểu đồ tròn nhưng không có source code: CloseSourceCode.BarChart. Tuy có thói quen đạo code thiên hạ:bbpcuoi3:, nhưng chương trình của tôi đã thiết kế với tính loose coupling rất cao nên đã sửa lại code của tên sinh viên đó, và truy xuất lớp đó qua Interface: IMyChart. Như vậy với cách làm thông thường tôi không thể sử dụng lớp CloseSourceCode.BarChart được vì CloseSourceCode.BarChart không thuộc interface IMyChart. Nhờ tìm hiểu kĩ về Adapter Pattern, tôi biết rằng có thể áp dụng Object Adapter Pattern trong trường hợp này. Tôi sẽ làm một lớp ThoaiChart (Thoại là tên tôi) implement từ interface IMyChart, và bên trong ThoaiChart tôi sẽ sử dụng lớp CloseSourceCode.BarChart để vẽ. Thiết kế lớp như sau:

Object Adapter Pattern

B. Class Adapter Pattern (Inheritance-Way)

- Tôi đã rất mừng khi phát hiện ra rằng chỉ mất chút ít thời gian để làm cái BarChart. Nhưng khi đưa cho khách hàng, họ yêu cầu tôi phải sửa lại cái BarChart, phải cho người dùng thấy được số liệu khi rê chuột lên hình. Đúng là đồ free có khác, không khi nào dùng ngay được. Tôi đành phải thiết kế lại lớp ThoaiChart theo hướng khác. Bây giờ tôi sẽ inherit lớp CloseSourceCode.BarChart và override lại hàm hover chuột của nó. Thiết kế lớp như sau:

Class Adapter Pattern


IV/ So sánh Adapter Pattern với các Design Patterns khác?

- Trong các Design Pattern thuộc nhóm Structural Design Pattern, có rất nhiều mẫu có thiết kế lớp tương tự nhau. Chúng ta nên nắm rõ ý nghĩa và trường hợp sử dụng của chúng để không nhầm lẫn và … để khi em trai em gái nó hỏi còn biết đường trả lời :bbpbuon:. Trong phần so sánh giữa Adapter Pattern với các Design Patterns khác, tôi có nhắc nhiều đến từ interface của lớp (class). Bạn hãy hiểu đó như là kiểu(type) của lớp. Các lớp khác namespace và khác base class (base type) sẽ có interface khác nhau. Một số tác giả Việt Nam dịch interface của lớp là "giao diện của lớp", riêng cá nhân tôi thì thấy dịch như vậy cũng kì. Một điểm nữa là các bạn cần phân biệt interface trong trường hợp này với interface trong chữ GUI, và càng nên phân biệt nó với khái niệm interface trong một số ngôn ngữ lập trình như C#, Java, ...

• Với khả năng biến cái không thể thành có thể, Adapter Pattern làm cho 1 lớp có thể sử dụng được sau khi lớp đó đã được thiết kế xong trong khi Bridge Pattern làm điều đó trước khi lớp này được tạo ra.
• Bridge Pattern được nghĩ ra với ý tưởng tách rời những abstraction ra khỏi những implementation, và tạo tính độc lập cao giữa chúng. Trong khi đó, Adapter pattern đươc dùng để làm những lớp không liên quan (không cùng namespace, khác interface) có thể làm việc với nhau.
• Adapter Pattern về ý nghĩa sẽ biến đổi interface của một lớp, Proxy Pattern sẽ không đổi interface của một lớp và Decorator Pattern sẽ kế thừa và mở rộng dựa trên interface đó.
• Adapter Pattern khi dùng sẽ thay đổi interface của một đối tượng có sẵn để biến nó thành thứ có thể dùng được. Decorator Pattern sẽ phát triển thêm trên một đối tượng mà không làm thay đổi interface của nó
• Giống với Adapter Pattern, Façade Pattern có thể kết hợp nhiều xử lý vào một lớp mới đơn giản và gọn hơn , nhưng nó sẽ định nghĩa mới 1 interface trong khi Adapter Pattern tái sử dụng một interface (Trong ví dụ về các biểu đồ ở trên thì interface được tái sử dụng là IMyChart, không hề có một interface mới được tạo ra)


- Các bạn có thể tham khảo thêm những ví dụ code mẫu cho Adapter Pattern ở trang wiki. Ví dụ thứ hai ở trang này là biến đổi 1 lớp DList thành Stack dựa trên những xử lý có sẵn của DList mà không cần viết lại những xử lý phức tạp cho lớp Stack.

Tài liệu tham khảo:

Một câu chuyện về Bridge Pattern

- Mẫu thiết kế Bridge được thiết kế với ý tưởng tách rời những xử lý của một lớp ra lớp khác, từ đó có thể dễ dàng biến đổi hoặc thay thế mà không làm ảnh hưởng đến những nơi có sử dụng lớp ban đầu. Điều này có thể hiểu như sau: bạn thiết kế một lớp với rất nhiều xử lý, bây giờ bạn không muốn để những xử lý đó trong lớp của bạn nữa, bạn sẽ tạo ra một lớp mới và move toàn bộ những xử lý đó sang lớp mới. Khi đó trong lớp cũ sẽ giữ một đối tượng thuộc về lớp mới, và đối tượng này sẽ chịu trách nhiệm xử lý thay cho lớp ban đầu. Tại sao chúng ta làm như vậy và cách thực hiện như thế nào? Hi vọng với bài viết này chúng ta tìm được lời giải thích cho 2 câu hỏi trên.

- Mẫu Bridge về khía cạnh nào đó khá giống với mẫu Adapter ở chỗ: người ta sẽ nhờ vào một lớp khác để thực hiện một số xử lý nào đó. Tuy nhiên, ý nghĩa và mục đích sử dụng của hai mẫu thiết kế này hoàn toàn khác nhau. Mẫu Adapter Pattern hay còn gọi là Wrapper pattern được dùng để biến đổi một lớp/interface sang một dạng khác có thể sử dụng được. Adapter Pattern giúp nhiều lớp có thể làm việc với nhau dễ dàng mà bình thường không thể. Một trường hợp tôi gặp phải và có thể áp dụng Adapter Pattern là khi tôi không thể kế thừa lớp A nhưng muốn làm một lớp B có những xử lý tương tự như lớp A. Khi đó tôi làm lớp B như sau, các xử lý của B sẽ gọi những xử lý của A khi cần:bbpraroi:

Adapter Pattern Example

Hình 1: Ví dụ về mẫu Adapter


- Đó chỉ là một trong nhiều cách sử dụng có thể có của mẫu Adapter, tôi sẽ nói thêm về Adapter trong một bài viết khác, ở đây chỉ nêu ra ý nghĩa khác nhau của hai mẫu thiết kế này. Trước khi đi vào câu chuyện của mẫu Bridge, chúng ta hãy xem sơ đồ lớp của mẫu Bridge:

Bridge Pattern

Hình 2: Sơ đồ lớp của mẫu Bridge


Câu chuyện về mẫu thiết kế Bridge (Bridge Pattern)

- Có một người đã làm nghề đầu bếp đã 20 năm. Ông ta đã đi rất nhiều nơi trên thế giới, làm việc cho rất nhiều nhà hàng khác nhau và đã học được cách nấu rất nhiều món ngon. Không những thế ông ta còn sáng tạo ra những món đặc biệt cho riêng mình nữa. Nhờ tài nghệ của ông, các nhà hàng nơi ông làm luôn luôn đông khách. Sau 20 năm nhìn lại, ông thấy đã đến lúc mình phải mở nhà hàng cho riêng mình. Đã để dành được một số vốn kha khá, ông quyết định chọn một trong những thành phố năng động của Việt Nam là TPHCM để bắt đầu sự nghiệp riêng. Thế là nhà hàng của ông ta ra đời và kinh doanh khá phát đạt nhờ vào danh tiếng và tài nghệ của mình. Ông ta dành hết tâm huyết để tự tay nấu mọi món ngon nhất cho các thực khách vì không tin tưởng vào các phụ bếp được thuê. Càng ngày danh tiếng của nhà hàng càng được nhiều người biết đến, không chỉ những người sành ăn trong nước mà cả những du khách nước ngoài cũng tìm đến nhà hàng này để thưởng thức khi có cơ hội ghé đến TPHCM. Ông ta rất vui mừng trước doanh thu ngày càng cao nhưng bên cạnh đó cũng rất lo cho sức khỏe của mình, vì ông phải đứng chế biến món ăn từ 6h sang đến 11h đêm hằng ngày:bbpbuon:

- Các con của ông rất thương bố mình và khuyên ông nên truyền nghề lại cho các học trò, các người ấy sẽ giúp ông làm việc cho nhà hàng. Suy nghĩ khá lâu, ông thấy rằng các con ông nói rất có lý. Ông ta chọn 1 đứa học trò ngoan và giỏi nhất truyền toàn bộ những gì mình biết. Sau khi đã lĩnh hội được toàn bộ khóa học, đứa học trò đã phụ ông nấu nướng cho nhà hàng, nhờ vậy ông được rảnh rổi về sớm đi tập thể dục thẩm mỹ và làm những việc quản lý, mở rộng kinh doanh.

- Thời gian trôi qua, ông muốn mở thêm một nhà hàng mới ở HN. Cũng trong giai đoạn này, ông nhận được email của một số khách ruột bảo rằng chất lượng món ăn bắt đầu kém đi, không đậm đà như trước đây. Sau khi tìm hiểu, ông phát hiện nguyên nhân là do thằng học trò đểu cáng đang âm mưu mở nhà hàng riêng nên nó lơ là việc nấu nướng :bbpnodo:, ngoài ra do ông dạy nó nhiều quá nên nó chỉ có thể nấu ngon được một số món ăn, phần lớn các món khác nấu không đạt yêu cầu. Rút kinh nghiệm, ông quyết định đăng báo dân trí tìm một số cô gái thích nấu nướng truyền cho mỗi cô 1 kĩ thuật nấu món ngon các miền. Sau này nếu có ý định mở nhà hàng ở miền Trung cũng sẽ có đầu bếp chuyên nấu món cay hợp khẩu vị của dân địa phương.


Bridge Pattern Example


Hình 3: Bản kế hoạch mở 2 nhà hàng mới của ông


// Bridge pattern -- Structural example
using System;
namespace nthoai.blogspot.com.BridgePattern
{

// "Abstraction"
class NhaHang
{

protected DauBep _dauBep;

// Property
public DauBep DauBep
{

set { _dauBep = value; }

}

public virtual void CheBienMonAn()
{

_dauBep.CheBienMonAn();

}

}

// "Implementor"
abstract class DauBep
{

public abstract void CheBienMonAn();

}

// "Nhà hàng món Huế"
class NhaHangMonHue : NhaHang
{

public override void CheBienMonAn()
{

_dauBep.CheBienMonAn();

}

}

// "Nhà hàng món miền Nam"
class NhaHangMienNam : NhaHang
{

public override void CheBienMonAn()
{

_dauBep.CheBienMonAn();

}

}

// "ConcreteImplementorA"
class DauBepMonAnHue : DauBep
{

public override void CheBienMonAn()
{

Console.WriteLine("Đây là những món ăn Huế do đầu bếp Huế thực hiện");

}

}

// "ConcreteImplementorB"
class DauBepMonAnMienNam : DauBep
{

public override void CheBienMonAn()
{

Console.WriteLine("Đây là những món ăn miền Nam do đầu bếp miền Nam thực hiện");

}

}

// Ông đầu bếp mở nhà hàng như sau
class ÔngĐầuBếpGià
{

static void Main()
{

NhaHang _nhaHangMonHue = new NhaHangMonHue();

// Set implementation and call
_nhaHangMonHue.DauBep = new DauBepMonAnHue();
_nhaHangMonHue.CheBienMonAn();

NhaHang _nhaHangMonMienNam = new NhaHangMienNam();
// Change implemention and call
_nhaHangMonMienNam.DauBep = new DauBepMonAnMienNam();
_nhaHangMonMienNam.CheBienMonAn();

// Wait for user
Console.Read();

}

}

}


Hình 4: Kế hoạch mở nhà hàng :D

- Câu chuyện của ông đầu bếp già là một ví dụ về cách sử dụng của Bridge khi đưa những xử lý sang một lớp khác. Trong các tài liệu về mẫu Bridge, các tác giả thường sử dụng các thuật ngữ như: Abstraction, Implementor, RefinedAbstraction và ConcreteImplementor. Cá nhân tôi thấy những từ vô cùng chuyên môn như vậy hơi khó hiểu, tôi thích những ví dụ thực tế hơn, tuy nhiên những từ ấy hoàn toàn chính xác. Sử dụng mẫu Bridge trong lập trình không chỉ đơn giản là đưa những xử lý của một lớp sang lớp khác rồi gọi nó từ lớp mới, mọi việc không chỉ đơn giản như vậy. Ý tưởng trên chỉ là một vế của Bridge Pattern, ở đây chúng ta chưa nói đến vế: “từ đó có thể dễ dàng biến đổi hoặc thay thế mà không phải ảnh hưởng đến những nơi có sử dụng lớp ban đầu” (so you can vary or replace the implementation without changing the client code). Xin thưa với các bạn đây chỉ là cách diễn giải của tôi, không phải khái niệm hay định nghĩa tiếng Việt của Bridge Pattern cho nên nếu các bạn muốn xem nguồn tiếng Anh hãy chịu khó google. Quay lại chỗ “biến đổi, thay thế mà không ảnh hưởng”, tôi đã có viết về chuyện này ở loạt bài về Dependency Injection của Spring.NET. Trong trường hợp của mẫu Bridge, chúng ta có thể giảm sự phụ thuộc giữa các lớp với nhau bằng cách sử dụng Interface hoặc abstract class. Trong các tài liệu về Bridge Pattern, các Abstraction và Implementer là những lớp abstract hoặc interface. Trong khi đó, các RefinedAbstraction và ConcreteImplementor là những thể hiện cụ thể hay những lớp con của các abstract class/ interface nói trên. Như vậy trong câu chuyện ông đầu bếp của chúng ta thì Abstraction là NhàHàng, RefinedAbstraction chính là Nhà Hàng Món Huế, Nhà Hàng Món Nướng Nam Bộ, Nhà Hàng Châu Âu còn ConcreteImplementor là các đầu bếp: Đầu Bếp Món Âu, Đầu Bếp Món Huế, …

- Như vậy chữ Bridge (chiếc cầu) ở đây là quan hệ “use/have” giữa Abstraction và Implementation, giữa Nhà Hàng và Đầu Bếp. Một RefinedAbstraction sẽ không khai báo cụ thể một ConcreteImplementor nào đang được sử dụng mà chỉ biết nó đang có 1 Implementor nào đó; khi mở một Nhà Hàng mới ta sẽ mướn Đầu Bếp (biết nấu ăn), còn cụ thể đầu bếp nấu được món miền nào sẽ quyết định lúc chọn xong địa điểm:bbpnghi:

- Trong một số trường hợp, mẫu thiết kế Bridge được dùng như một cầu nối giữa 2 nhóm đối tượng khác nhau, giữa nhóm các dữ liệu và nhóm các cách thể hiện ra màn hình, đó là ví dụ thường được dùng trong các bài viết về mẫu Bridge. Như chúng ta biết có rất nhiều chuẩn hình ảnh như JPG, PNG, BMP, GIF, … và các hệ điều hành khác nhau như Windows, MacOS, UNIX đều hiểu và có thể hiển thị các định dạng ảnh này.

- Cấu trúc hình ảnh và cách hiển thị chúng là hai thành phần quan trọng của một định dạng ảnh. Cấu trúc hình chính là cách mà hình đó được lưu trữ, và cách thể hiện chúng sẽ tương đối khác nhau trên các chương trình xem hình trên các hệ điều hành khác nhau. Trong trường hợp này các file hình với các định dạng khác nhau sẽ thường xuyên thay đổi, và các hệ điều hành cần vẽ hình cũng nhiều tương tự. Nếu được yêu cầu thiết kế lớp cho bài toán trên sao cho tính tái sử dụng cao nhất, bạn sẽ làm thế nào. Như đã nói, có rất nhiều chuẩn hình, mỗi hình sẽ có những thông tin riêng của nó và mỗi hình nên được thiết kế để có khả năng tự vẽ nó (Information Expert) . Nhưng vì cách vẽ sẽ khác nhau trên các hệ điều hành khác nhau nên nếu chúng ta thiết kế lớp hình tự thực hiện hàm vẽ rồi khi cần thì sửa hàm vẽ để nó hoạt động được trên hệ điều hành khác là không nên. Bridge Pattern sẽ giúp ta đưa những hàm vẽ đó sang những lớp khác để vẽ trên các hệ điều hành tương ứng. Nhờ vậy, khi một chuẩn hình mới được tạo ra hay có một thuật toán vẽ khác được nghĩ ra, sẽ rất dễ dàng để ta code thêm một lớp vẽ mới cho chương trình.

- Một ví dụ khác cũng tương tự là khi bạn cần xây dựng một ứng dụng thể hiện ra màn hình thông tin khác nhau với những loại user khác nhau. Cùng một dữ liệu nhưng nếu là Admin bạn sẽ cho phép hiển thị chi tiết hơn, có thêm những button cho phép edit hoặc delete chẳng hạn. Trong khi đó user thường hoặc guest chỉ có thể xem mà không thể làm gì khác. Còn rất nhiều trường hợp khác mà chúng ta có thể dùng Bridge cũng như có nhiều mẫu thiết kế tương tự Bridge như Strategy, Adaptor. Nếu chúng ta nắm được ý nghĩa, sự khác nhau và khi nào nên áp dụng những thiết kế này của 4 lão tiền bối thì công việc lập trình sẽ hứng thú, đầy tính sáng tạo và không nhàm chán chút nào. Hi vọng đến đây chúng ta đã tìm được câu trả lời cho 2 câu hỏi trên. Tôi sẽ bàn thêm một chút về những lợi ích và trở ngại khi sử dụng Bridge:

Benefits in using Bridge Pattern

1/ Đặt vấn đề: chúng ta có một lớp A, và các lớp A1, A2, A3 kế thừa từ lớp A. Các lớp A1, A2, A3 sẽ được thừa hưởng các attribute và behavior của lớp A. Như vậy vô tình các xử lý của lớp A1, A2, A3 sẽ y như A trừ khi chúng phải override lại. Trong chương trình, khi cần sử dụng một trong các lớp A1, A2, A3 người ta thường khai báo chung chung là A thay vì khai báo cụ thể là ta sẽ gọi mày đó A1, A2, A3. Cách sử dụng lớp A ta gọi là abstraction hay là trừu tượng hóa và những xử lý của lớp A mà các A1, A2, A3 thừa hưởng gọi là implementation. Sử dụng thiết kế Bridge sẽ giúp chúng ta giảm sự phục thuộc giữa abstraction và implementation. Tính kế thừa trong hướng đối tượng thường gắn chặt abstraction và implementation lúc build chương trình. Bridge Pattern có thể được dùng để cắt đứt sự phụ thuộc này và cho phép chúng ta chọn implementation phù hợp lúc runtime.

2/ Giảm số lượng những lớp con không cần thiết. Một số trường hợp sử dụng tính inheritance sẽ tăng số lượng subclass vô tội vạ. Ví dụ trường hợp chương trình xem hình trên các hệ điều hành khác nhau, ta có 6 loại hình và 3 hệ điều hành. Sử dụng inheritance trong trường hợp này sẽ làm ta thiết kế 18 lớp trong khi áp dụng Bridge sẽ giảm số lượng lớp xuống 9:bbpcuoi1:

3/ Lợi ích thứ 2 dẫn đến một hệ quả: Code sẽ gọn gàn hơn và dẫn đến kích thước ứng dụng sẽ nhỏ hơn.

4/ Các Abstraction và Implementation của nó sẽ dễ dàng thay đổi lúc runtime cũng như khi cần thay đổi thêm bớt trong tương lai. Như vậy chương trình của chúng ta cũng sẽ dễ bảo trì hơn.

5/ Tương tự như lợi ích 4, nếu sử dụng Bridge, hệ thống sẽ dễ mở rộng về sau. Đây hầu như là một yêu cầu bắt buộc đối với các chương trình lớn. Nhiều công ty sẽ cùng làm trong từng giai đoạn phát triển. Một số công ty phần mềm ở VN thường làm outsource: maintain hoặc mở rộng một framework hay một chương trình đã được làm sẵn ở nước ngoài. Công ty khách hàng sẽ yêu cầu chúng ta thêm module cho ứng dụng có sẵn nhưng không được sửa đổi framework/ứng dụng có sẵn của họ vì các framework/ứng dụng đó có thể được công ty nâng cấp lên version mới. Đó là bài toán các bạn sẽ gặp phải khi làm ở những project trung bình và lớn, và ta sẽ vô cùng bực mình và cảm thấy khó khăn khi framework/chương trình đó được đám lập trình viên ở đâu đâu code vô cùng chuối giờ lại bắt mình viết thêm vào:bbptuc:

6/ Những nơi cần sử dụng các abstraction sẽ hoàn toàn độc lập với các implementation.Ví dụ các lớp khác của chương trình xem ảnh sẽ độc lập với thuật toán vẽ ảnh trong các implementation. Như vậy ta có thể update chương trình xem ảnh khi có một thuật toán vẽ ảnh mới mà không cần phải sửa đổi nhiều thậm chí build lại toàn chương trình nếu có dùng các kĩ thuật Dependency Injection.

1 Drawbacks in using Bridge Pattern

- Khi sử dụng Bridge Pattern, chúng ta đã tăng số lần gọi gián tiếp lên hai. Trong ví dụ trên, với cách làm cũ, lớp Image sẽ thực hiện hàm vẽ của chính nó. Nếu áp dụng Bridge, hàm vẽ sẽ được gọi thông qua một lớp implementation tương tứng như vậy có thêm một lần khởi tạo đối tượng và gọi đối tượng, có thêm một lần hủy đối tượng và lượng bộ nhớ bị chiếm để chạy chương trình sẽ tăng lên một chút. Theo tôi những bất lợi này vô cùng không đáng kể so với những lợi ích mang lại khi chúng ta áp dụng Design Pattern nói chung và Bridge Pattern nói riêng.

-----------------------------------------------------------------

- Cuối cùng, ông đầu bếp già của chúng ta sẽ không có thời gian đi massage hay đi chơi gôn nếu cứ tiếp tục tự nấu ăn. Nhà hàng của ông sẽ rất khó khăn khi đầu bếp chính nghỉ việc nếu không có nhiều đầu bếp giỏi chuyên môn. Thử tưởng tượng trong thực tế chúng ta mua một chiếc xe gắn máy mà khi hư thì phải bỏ đi và mua xe mới thay vì có phải tìm phụ tùng thay thế. Tính độc lập, chuyên môn hóa giữa các bộ phận trong một hệ thống luôn được đề cao trên mọi lĩnh vực trong cuộc sống. Riêng trong thiết kế phần mềm, design pattern là những bài học kinh nghiệm mà khi áp dụng tốt sẽ biến người lập trình thành một nghệ sĩ. Một lần nữa, tôi hi vọng bài viết này không chỉ giúp các bạn biết Bridge Pattern là gì mà còn hiểu được tại sao và khi nào cần nó. Tóm lại, cách sử dụng inheritance một cách máy móc có thể vô tình dán chặt những abstraction và implementation với nhau trong khi một số ứng dụng cần điều ngược lại. Bridge Pattern có thể được sử dụng khi một abstraction có nhiều implementation và cả 2 nhóm có thể có nhiều thay đổi mà không phụ thuộc hoặc ảnh hưởng gì nhóm còn lại:bbpcuoi5:



Các tài liệu tham khảo:

rss
 

About Me

Place I've live
Near Bossley Park, Sydney, NSW, Australia
Place I've work
  • Freelancer (from 06/2010 to present)
  • Harvey Nash (from 05/2008 to 06/2010)
  • DataDesign Vietnam (10/2005 to 04/2008)
Place I've studied
  • University of Natural Science (Bachelor of Science HoChiMinh City Vietnam From 2001 to 2005)
  • Le Hong Phong High School (HoChiMinh City Vietnam From 1997 to 2000)