Datgs' Blog

Quyết chiến quyết thắng !

Archive for the tag “Design Pattern”

Design Pattern: Sự khác nhau giữa Bridge và Strategy (Policy)

Nghiên cứu về design pattern, việc nắm vững bản chất của các Pattern là rất quan trọng. Nếu không sẽ rất dễ nhầm lần giữa các Design Patterns với nhau.

Bridge Pattern và Policy Pattern là một ví dụ. Bạn có thể tìm thấy tài liệu về chúng ở khắp nơi trên Google. Chúng hao hao giống nhau nếu bạn cứ dán mắt vào mấy cái Diagram. Và sự thật là phải mất nhiều thời gian mình mới phân biệt được chúng. Vậy sự khác nhau giữa chúngđây là gì:

1. Brige Pattern là để tách rời phần xử lý (giải thuật…) với phần chủ thể (nơi thực thi các giải thuật đó). Phần xử lý hầu như chỉ có tác dụng bên trong phần chủ thể và không bao giờ được sử dụng ở các nơi khác. Ngoài ra các phần xử lý hầu như chỉ sử dụng cho chủ thể tương ứng (ví dụ nếu ta xác định một Bridge giữa 2 class A và A’ thì class A’ sẽ chỉ được xử dụng trong A và không sử dụng trong B (cùng abstract với A)

Đúng như tên gọi của nó, Brige Pattern bao gồm phần Abstract định nghĩa 2 đầu của một cây cầu. Các Implementation triển khai các Abstract đó thành từng cặp, và chỉ dùng theo cặp. Không có mục đích “thay đổi linh hoạt” như Strategy Pattern.

Chú ý là không chỉ là Brige giữa các cặp đôi, mà Bridge có thể mở rộng cho một bộ các “đầu mối” khác nhau nữa.

Ví dụ bạn Abstract của một hoạt động Import dữ liệu bao gồm:
- Phần đọc dữ liệu/ Chuẩn hóa dữ liệu/ Lưu nháp
- Phần validator, đảm bảo dứ liệu tuân thủ business
- Phần Intergration, đưa dữ liệu vào cơ sở dữ liệu thực

Tại sao lại dùng Bridge ở đây. Đơn giản là vì: thứ nhất bạn phải kết nối giữa 3 “đầu cầu” trên. Thứ hai, khi bạn Import Addresses, Import Products… bạn không thể sử dụng Validator của Import Address làm validator của Import Products được.

Hữu ích: bạn có thể dễ dàng thay đổi nâng cấp của Import Addresses mà không cần quan tâm đến business của Import Products có thay đổi hay không. Đây gọi là nâng cấp từng phần.

2. Strategy (Policy) Pattern thì khác, một chủ thể có thể sự dụng linh hoạt khác policy khác nhau.

Đó giải thích tên gọi của nó, “Chiến lược”. Chiến lược gì? Chiến lược sử dụng các triển khai của Abstract. Lúc này tôi có rất nhiều dữ liệu tôi muốn sử dụng Quick Sort, lúc khác tôi chỉ có vài phần từ thôi nên tôi dùng Bubble Sort là đã ok rồi….

Design Pattern – Structural Pattern – Bridge Pattern

Đúng như tên gọi Bridge Pattern, đây là kiểu cấu trúc cầu nối giữa “các bên”, bên thực thi và bên chủ đầu tư :D .

Xem http://nthoai.blogspot.com/2008/05/mot-cau-chuyen-ve-bridge-pattern.html

Đó là một ví dụ cực kỳ thú vị về bridge pattern.

Cũng giống như Adapter pattern, các bên thực thi có cùng nhiệm vụ, nhưng khác ở chỗ kết xuất ra những kết quả khác nhau. Mỗi chủ đầu tư có một yêu cầu kết quả riêng và thường chỉ có một đơn vị thực thi có thể thỏa mãn.

Design Pattern – Creational Pattern – Abstract Factory Pattern

Abstract Factory Pattern được sử dụng khi ta muốn nhóm các factories sản xuất các products có cùng một kiểu hành động.

Ví dụ các Database khác nhau, có cách cấu thành câu truy vấn SQL khác nhau (quotes, delimiter…) (products khác nhau), vì vậy chung một tình huống là truy vấn dữ liệu, và giả sử ta có chung một đối tượng dữ liệu truy vấn cho các products là SelectObject, ta sẽ có:

abstract SQL_Factory with virtue createSqlString(SelectObject) methods
MySQL_Factory extends SQL_Factory implements createSqlString(SelectObject)
MsSQL_Factory extends SQL_Factory implements createSqlString(SelectObject)

In the application:

if(db_adapter == MySQL) $db_Factory = new MySQL_Factory
if(db_adapter == MsSQL) $db_Factory = new MsSQL_Factory
/* Do something to create SelectObject*/
$sql = $db_Factory->createSqlString(SelectObject)
/* Use db connection to execute the sql*/
$results = $db_Factory->getDbConnection()->execute($sq);

Design Pattern – Creational Pattern – Prototype (nguyên mẫu)

Trong phát triển phần mềm, prototype pattern được sử  dụng khi bạn muốn tạo ra một đối tượng có kiểu đã được quy định bởi một thực thể mẫu bằng cách sao chép thực thể ấy để tạo thành đối tượng mới.

Prototype pattern được sử dụng trong trường hợp:

+ Tránh việc tạo nhiều lớp con cho mỗi đối tượng tạo như của abstract factory pattern
+ Giảm chi phí để tạo ra một đối tượng mới theo “chuẩn”, tức là việc này tăng performance so với việc sử dụng từ khóa new để tạo đối tượng mới

Để cài đặt prototype pattern, tạo ra một clone() method ở lớp cha, và triển khai ở các lớp con.

Design Pattern – Behavior Pattern – Stragety (Policy) Pattern

Là mẫu thiết kế “chiến lược” sử dụng các giải thuật khi chạy chương trình.
Trong các ngôn ngữ lập trình không hỗ trợ tính đa hình, vấn đề liên quan đến Design Pattern này được điều khiển bởi các mẫu phản chiếu (tham chiếu), giống như con trỏ (pointer).

Mẫu này không thấy ngay được trong các ngôn ngữ lập trình hàm (first-class function).

Mẫu này rất hữu dụng trong các tình huống cần phải thay đổi động các giải thuật (sử dụng các giải thuật khác nhau) trên một ứng dụng.

Ví dụ (có thể xem ở link này: http://www.cumps.be/design-patterns-strategy-pattern/) là một ví dụ rất hay về Stragety Pattern. Trong đó mô tả các đối tượng trong một game với chung một phương thức nhưng với cách thực hiện khác nhau.

Hoặc có thể xem http://en.wikipedia.org/wiki/Strategy_pattern có rất nhiều mã nguồn ví dụ bạn có thể tham khảo.

Design Pattern – Creational Pattern – Factory Method

1) Một phương án giải quyết vấn đề tạo object.

2) Câu hỏi là: Làm sao để tạo object mà không cần phải chỉ rõ class cụ thể của object đó là gì?

3) Lợi ích: cho phép chỉ rõ “nội dung” của đối tượng cần tạo. Thường sử dụng các hàm static.

4) Ví dụ về hàm tạo theo cách đặt tên mô tả:

class Complex
{
     public static Complex fromCartesian(double real, double imag) {
         return new Complex(real, imag);
     }

     public static Complex fromPolar(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }

     private Complex(double a, double b) {
         //...
     }
}

Complex c = Complex.fromPolar(1, pi); // Same as fromCartesian(-1, 0)

5) Ví dụ về hàm tạo theo các đóng gói:

public interface ImageReader {
    public DecodedImage getDecodedImage();
}

public class GifReader implements ImageReader {
    public DecodedImage getDecodedImage() {
        return decodedImage;
    }
}

public class JpegReader implements ImageReader {
    // ....
}
public class ImageReaderFactory {
    public static ImageReader getImageReader(InputStream is) {
        int imageType = determineImageType(is);

        switch(imageType) {
            case ImageReaderFactory.GIF:
                return new GifReader(is);
            case ImageReaderFactory.JPEG:
                return new JpegReader(is);
            // etc.
        }
    }
}

6) Hạn chế:

- Nếu hàm tạo (construct method) của class là private, sẽ không tạo được object bằng hàm tạo, mà buộc phải sử dụng hàm factory.
- Không thể mở rộng (kế thừa thêm nữa) ở các subclass nếu hàm tạo là private.
- Không còn đúng cho các subclass. Nếu có subclass gọi hàm factory, nó trả về instance của class chứ khôngphải là nó.

- Giải quyết: cần phải có sự hỗ trợ thêm nữa của các ngôn ngữ lập trình.

Singleton design pattern

Singleton là một design pattern khá là sơ đẳng. Kiểu lập trình này trong OOP cho phép khởi tạo đối tượng một lần (ví dụ như tạo kết nối với CSDL chẳng hạn, bạn chỉ cần mở kết nối một lần và thực hiện rất nhiều truy vấn trên cùng kết nối đó. Chứ không cần cứ mối truy vấn lại kết nối lại một lần.

Trong C#, Singleton được cài đặt như  sau

class Singleton

{

/* biến static instance, tạo instance một lần ở đây, những lần sau sẽ sử dụng lại*/

private static Singleton instance;

private static int numOfReference;

private string code;


private Singleton()

{

numOfReference = 0;

code = “Maasoom Faraz”;

}


public static Singleton GetInstance()

{

/* rất đơn giản, nếu instance đã tồn tại thì trả về , ngược lại một instance mới sẽ được tạo ra và trả về */


if(instance == null)

{

instance = new Singleton();

}

numOfReference++;

return instance;

}


public static int Reference
{

get { return numOfReference; }

}

public string Code
{

get { return code; }

set { code = value;}

}

}

Post Navigation

Follow

Get every new post delivered to your Inbox.