[Design Pattern] Command Pattern
Java
70
design pattern
20
White

Nguyễn Tuấn Anh viết ngày 18/05/2018

Design pattern luôn là một lĩnh vực khá khó nhằn và hơi trừu tượng. Trong bài viết này, mình sẽ giới thiệu về một pattern có tên là Command, với ví dụ trong bài viết hi vọng giúp các bạn dễ hiểu hơn về pattern này.


Giới thiệu

Command là một trong 23 design pattern Gang of Four nổi tiếng. Command thuộc nhóm các pattern hành vi.

Gang of Four chỉ ra mục đích sử dụng của pattern Command như sau:

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

Đoạn trên xem ra có vẻ hơi trừu tượng. Nhưng chúng ta có thể hiểu đơn giản như thế này: request từ phía người dùng sẽ được đóng gói dưới dạng một đối tượng command và đối tượng command này sẽ được chuyển cho một thành phần riêng biệt để thực thi. Pattern Command sẽ phân tách quá trình tiếp nhận request với quá trình thực thi request. Chính vì vậy, công việc xử lý request sẽ trở nên linh hoạt và dễ nâng cấp hơn. Điều này cũng giống như trong thực tế, người phục vụ sẽ chỉ quan tâm đến món ăn mà thực khách yêu cầu, còn việc chế biến món ăn ấy ra sao thì đã có đầu bếp của nhà hàng lo rồi.

Bên cạnh đó, trong pattern Command, chúng ta có thể lưu vết các command đã thực hiện. Nhờ điều này mà pattern Command còn được áp dụng cho tác vụ undo/redo trong các ứng dụng thực tế.


Cấu trúc

UML của pattern Command:

Command Pattern UML

Pattern Command gồm 5 thành phần chính:

  • Command: đây có thể là một interface hoặc abstract class, chứa một abstract method execute(). Request sẽ được đóng gói dưới dạng Command.
  • Concrete Command: là các implementation của Command, mỗi một Concrete Command sẽ phục vụ cho một case request riêng.
  • Receiver: đây mới là thành phần thực sự xử lý business logic cho case request. Trong method execute() của Concrete Command, chúng ta sẽ gọi method thích hợp trong Receiver.
  • Client: tiếp nhận request từ phía người dùng và đóng gói request thành Concrete Command thích hợp.
  • Invoker: tiếp nhận Concrete Command từ Client và gọi execute() của Concrete Command để thực thi request. Việc lưu vết command sẽ được thực hiện ở trong Invoker.

Như vậy, Client và Invoker sẽ thực hiện việc tiếp nhận request. Còn việc thực thi request sẽ do Command, Concrete Command và Receiver đảm nhận.


Ví dụ

Trong ví dụ này, chúng ta sẽ thử áp dụng pattern Command vào bài toán order món ăn tại một nhà hàng. Đầu tiên, khách hàng (customer) sẽ order món ăn. Với từng món ăn (steak hoặc pizza) thì người phục vụ (waiter) sẽ chuyển order cho đầu bếp (chef) chuyên chế biến món đó. Với bài toán này, chúng ta có thể thấy:

  • Order sẽ đóng vai trò Command.
  • Steak và Pizza chính là các Concrete Command.
  • Steak Chef và Pizza Chef đóng vai trò Receiver.
  • Customer đóng vai trò Client.
  • Waiter sẽ là cầu nối giữa Customer và Chef: Invoker.

Dưới đây là chi tiết cài đặt cho bài toán này:

Order.java

public interface Order {

    void execute();

}

Pizza.java

public class Pizza implements Order {

    private PizzaChef chef;

    public Pizza(PizzaChef chef) {
        this.chef = chef;
    }

    @Override
    public void execute() {
        chef.makePizza();
    }

    @Override
    public String toString() {
        return "pizza";
    }

}

Steak.java

public class Steak implements Order {

    private SteakChef chef;

    public Steak(SteakChef chef) {
        this.chef = chef;
    }

    @Override
    public void execute() {
        chef.makeSteak();
    }

    @Override
    public String toString() {
        return "steak";
    }

}

PizzaChef.java

public class PizzaChef {

  public void makePizza() {
    System.out.println("I'm making pizza");
  }

}

SteakChef.java

public class SteakChef {

  public void makeSteak() {
    System.out.println("I'm making steak");
  }

}

Waiter.java

import java.util.ArrayList;
import java.util.List;

public class Waiter {

  // Track orders
  private List<Order> orders = new ArrayList<>();

  public void takeOrder(Order order) {
    System.out.println("Waiter taked new order " + order.toString());
    orders.add(order);
    order.execute();
  }

}

Customer.java

public class Customer {

    public static void main(String[] args) {
      // Invoker
      Waiter waiter = new Waiter();

      // Receivers
      PizzaChef pizzaChef = new PizzaChef();
      SteakChef steakChef = new SteakChef();

      // Commands
      Order pizza = new Pizza(pizzaChef);
      Steak steak = new Steak(steakChef);

      // Test
      waiter.takeOrder(pizza);
      waiter.takeOrder(steak);
    }

}

Chạy file Customer.java, chúng ta sẽ có kết quả như sau:

Waiter taked new order pizza
I'm making pizza
Waiter taked new order steak
I'm making steak

Link soure code: https://github.com/yuen26/tutorial-design-pattern/tree/master/command/order

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Nguyễn Tuấn Anh

9 bài viết.
69 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
33 28
MyContact là một ứng dụng mà mình thường viết mỗi khi học một ngôn ngữ hay công nghệ mới. MyContact chỉ là một ứng dụng CRUD đơn giản, cho phép ngư...
Nguyễn Tuấn Anh viết hơn 1 năm trước
33 28
White
19 11
Hướng dẫn lập trình Spring Security Trong bài viết lần này, mình sẽ giúp các bạn bước đầu tìm hiểu (Link) thông qua xây dựng các chức năng: Đăng ...
Nguyễn Tuấn Anh viết hơn 1 năm trước
19 11
White
11 0
Giới thiệu Spring Framework Trong bài viết này, mình sẽ giới thiệu cho các bạn về một trong những Java EE framework rất nổi bật và phổ biến hiện ...
Nguyễn Tuấn Anh viết hơn 1 năm trước
11 0
Bài viết liên quan
White
0 0
Trong bài viết này, một số hình ảnh hoặc nọi dung có thể bị thiếu do quá trình chế bản. Vui lòng xem nội dung ở blog gốc sau: (Link) (Link), chúng...
programmerit viết gần 3 năm trước
0 0
Male avatar
9 5
Facade Design Patern Facade Patern thuộc vào họ mô hình cấu trúc (structural patern). Facade patern phát biểu rằng : "just provide a unified an...
DuongVanTien viết hơn 1 năm trước
9 5
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
9 bài viết.
69 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!