Welcome to Comedown's Blog Technology !
Loading...

Command Pattern

Người đăng: Unknown Thứ Tư, 15 tháng 7, 2009 Lượt xem: counter


Đang có nhu cầu refactoring đoạn code trong cty và muốn dùng Command Pattern nên đọc lại nó một chút. Ngoài cuốn sách của GoF kinh điển thì cuốn Head First - Design Patterns của nhà xuất bản O'reilly khá hay, nó lấy ví dụ trong cuộc sống và cách trình bày làm cho người đọc cảm thấy ít khô khan hơn.

Issue được đưa ra từ ví dụ sau: có một cái remote control có nhiều khe (slot), mỗi khe có thể được lập trình để điều khiển các thiết bị khác nhau. Có hai nút cho mỗi khe là On/Off, một nút Undo dùng chung cho tất cả các khe (xem hình)


Có nhiều thiết bị khác nhau, như quạt, đèn, TV, máy nước nóng (hottub)... Ta phải lập trình sau cho remote control có khả năng bật tắt trên các thiết bị đó, tùy vào ngữ cảnh user nạp thiết bị vào trong slot nào.

Ý nghĩ đầu tiên về cách lập trình:

if (slot1 == light) light.on();
else if (slot1 == hottub) hottub.on();
else....

--> chuối quá.

Có cách nào tách rời giữa remote control và các vendor class, nó không cần biết phải bật/tắt trên class nào, chỉ đơn giản là execute một command, không quan tâm bên trong command đó làm việc gì (bản thân command tự biết). Đây gọi là decouple requester của một action và object thực hiện action đó.

Command pattern thực hiện như sau:

* Tạo ra một command object encapsulate một request làm một action nào đó (giống như turn on a light) và trên một đối tượng nào đó (vd trên đối tượng bóng đèn).

* Store command object đó. Invoker khi có nhu cầu sẽ gọi execute trên command đó (giống như load các command trên mỗi button, khi user nhấn nút thì gọi command execute, không quan tâm đến nó làm cái gì)

Implementation

Tạo ra 1 interface chung Command

public interface Command {
public void execute();
}

public class LightOnCommand implements Command {
Light light;

public LightOnCommand(Light light) {
this.light = light;
}

public void execute() {
light.on();
}
}

public class TestRemoteControl {
public void Test() {
RemoteControl remoteControl = new RemoteControl(); // class remoteControl tu viet

Light light = new Light();

LightOnCommand lightCommand = new LightOnCommand(light);

remoteControl.setCommandOnSlot(1, lightCommand); // set lightCommand on slot 1

remoteControl.pressButton(1); // simulate press button 1
}
}

Trở lại đoạn code cần refactor, có khá nhiều use cases trong business flow, làm thế nào để code vừa áp dụng được pattern trên vừa thể hiện rõ business mà nó đang chạy nhất.


Review document ta thấy có 4 dạng business chính, wrapper lại thành 4 command chính là MoneyTransferCommand, MobileRechargeCommand...

Các command này thực hiện action trên 2, 3 đối tượng là YP, BP (banking Pichincha), Commerce (third party), ... (trong command pattern, đối tượng này gọi là Receiver)

Code được viết như sau:

public class MoneyTransferCommand : Command
{
YP yp;
BP bp;

// .......

public void Execute()
{
transActionStatus = yp.ValidateTransaction(incoming);

swith(transactionStatus)
{
case SUCCESS:
bp.MoneyTransfer();

break;

//......
}
}
}

CommandFactory thực hiện việc tạo ra các command từ incoming rồi bỏ vào trong queue. Các thread sẽ thực hiện command trong queue


Nguồn :-Dzinh on tech [Chapter 6 - Design Patterns (Head First)]

0 nhận xét

Đăng nhận xét

1. Vui lòng nhập tiếng việt có dấu.
2. Không sử dụng từ ngữ thô tục, trái với thuần phong mỹ tục.
3. Nội dung phải liên quan tới chủ đề bài viết, bạn có thể sử dụng một số thẻ HTML như <b>, <i>, <a>
4. Những nhận xét mang tính chất Đồi trụy, Quảng cáo, Spam hoặc không có tính xây dựng... sẽ bị xóa vĩnh viễn mà không cần báo trước.

Bài đăng Mới hơn Bài đăng Cũ hơn Trang chủ
Blogumulus by Roy Tanck and Amanda FazaniInstalled by CahayaBiru.com

Followers

Cộng đồng Blogger

Comedown's Blog
TruongGTGR - Nơi siêu xe hội tụ
Tư vấn tin học