Chatbox

Các bạn vui lòng dùng từ ngữ lịch sự và có văn hóa,sử dụng Tiếng Việt có dấu chuẩn. Chúc các bạn vui vẻ!
15/08/2021 19:08 # 1
buiducduong
Cấp độ: 22 - Kỹ năng: 1

Kinh nghiệm: 17/220 (8%)
Kĩ năng: 0/10 (0%)
Ngày gia nhập: 25/09/2020
Bài gởi: 2327
Được cảm ơn: 0
Điều mà dev JS cần biết: Observe Design Pattern


Khái niệm

Hầu hết chúng ta khi làm việc với bất cứ ngôn ngữ hay framework nào cũng sẽ phải áp dụng một (vài) Design Pattern nhất định để giúp tiết kiệm và tái sử dụng các bộ code sẵn có, cũng như làm cho bộ code dễ đọc hơn, dễ bảo trì hơn hoặc để tận dụng tốt hơn sức mạnh của ngôn ngữ hoặc framework đó.

Trong bài viết này tôi sẽ giới thiệu và implement một Design Pattern được sử dụng trong Javascript có tên là Observer Design Pattern.

Vì phần khái niệm có khá nhiều các từ ngữ mà khi dịch ra tiếng Việt sẽ khá là kỳ cục và không mô tả được hết ý nghĩa nên mình xin phép giữ nguyên.

Một Observer Pattern hoạt động dựa trên ý tưởng: Một Subscriber (thường được gọi là The Observer) đăng ký theo dõi một sự kiện hoặc hành động nào đó được xử lý bởi một Publisher (còn được gọi là The Subject) sẽ được thông báo khi sự kiện hoặc hành động đó xảy ra.

Nghe thì có vẻ hơi lú tí nhưng thật ra nó không có khó hiểu lắm, hãy tưởng tượng đơn giản như việc bạn bấm subscribe một kênh Youtube vậy, mỗi khi kênh đó đăng một video hay cập nhật gì thì bạn cũng sẽ nhận được một thông báo và sau đó là việc bạn làm với thông báo đó là gì thôi. Ở đây The Observer chính là bạn, The Subject là kênh Youtube kia, khi kênh Youtube nhận được một lệnh đăng video mới của người chủ kênh, nó sẽ gửi thông báo đến cho bạn. Easy to understand!

Và đương nhiên kênh Youtube đó không chỉ có mỗi bạn là Observer mà nó còn nhiều các observer nữa, thông báo được gửi đến bạn đồng nghĩa với việc thông báo đó cũng được đồng thời gửi đến các Observer khác.

Việc gửi thông báo - nhận thông báo này sẽ xảy ra liên tục cho đến khi Observer không còn có nhu cầu nhận thông báo nữa, đồng nghĩa với việc Observer bấm nút bỏ subscribe kênh và kênh cũng sẽ loại Observer đó khỏi danh sách tiếp tục nhận thông báo.

Thiết lập Observer Design Pattern

Đã tìm hiểu nguyên lý hoạt động về mặt lý thuyết rồi, giờ đến ví dụ thực tế về cách hoạt động và cách implement pattern này.

Tôi sẽ làm một ví dụ đơn giản về cách các Observer tương tác khi chúng cùng lắng nghe một sự kiện nào đó nhưng mỗi Observer lại có một cách xử lý khác nhau khi sự kiện xảy ra.

Đây là một ví dụ kiểu như thế, nhiều Observer cùng xử lý sự kiện khi con chuột di chuyển, và mỗi Observer này sẽ có một cách xử lý khác nhau để điều khiển quả bóng xanh di chuyển mô phỏng lại chuyển động của chuột. Có một số điểm cần lưu ý như sau:

  • Subject sẽ lắng nghe hành động di chuyển của con chuột và thông báo đến cho các Observer
  • Observers sẽ bao gồm chấm màu xanh và ô màu đen ghi thông tin vị trí X Y của chuột

Các bước thiết lập

1. Khởi tạo Subject class

Class sẽ cần một số Property và Methods như sau:

  • List các Observer callback
  • Method subscribe(): Nhận vào các Observer và push Observer đó vào list các Observer đã Subscribe. Vì mỗi Observer sẽ xử lý một hành động khác nhau nên tham số đầu vào của method này sẽ là một callback và danh sách các Observer cũng là danh sách các callback.
  • Method handleMouseMove(): lắng nghe sự kiện khi chuột di chuyển và trigger sự kiện này đến các Observer
class MousePositionObservable {
  constructor() {
    this.subscriptions = [];
    window.addEventListener('mousemove', this.handleMouseMove);
  }
  handleMouseMove =  (e) => {
     this.subscriptions.forEach(sub => sub(e.clientX, e.clientY));
  }
  subscribe(callback) {
    this.subscriptions.push(callback);    

    return () => {
      this.subscriptions = this.subscriptions.filter(cb => cb !== callback);
    }
  }
}

2. HTML code

Tạo giao diện HTML để quan sát các Observer

<div class="container">
  <div class="circle" ></div>
  <div class="mouse-position">
  <h4>Mouse Position</h4>
  <div class="position"></div>
</div>
</div>
.container {
  position: relative;
  width: 100vw;
  height: 100vh;
  background-color: #f3df49;
}
.circle {
  position: absolute;
  background-color: #238643;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  z-index: 2;
}

.mouse-position {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 100px;
  background-color: black;
  border-radius: 4px;
  padding: 4px 16px;
  color: white;
}

.mouse-position h4 {
  color: white;
  margin: 10px 0;
}

3. Xử lý Subscribe

Giờ chúng ta cần khởi tạo Subject và cho các Observer này subscribe vào Subject

const mousePositionObservable = new MousePositionObservable();

// Observer chấm xanh 
mousePositionObservable.subscribe((x, y) => {
  const circle = document.querySelector('.circle');
   window.setTimeout(() => {
     circle.style.transform = `translate(${x}px, ${y}px)`;
   }, 1000);
});

// Observer của ô textbox
mousePositionObservable.subscribe((x, y) => {
  const board = document.querySelector('.mouse-position .position');
  board.innerHTML = `
    <div>
       <div>ClientX: ${x}</div>
       <div>ClientY: ${y}</div>
    </div>
  `
})

Lúc này các bạn có thể console thử danh sách các Observer và xem các thay đổi của chúng khi chuột di chuyển trên màn hình.

Dưới đây là phần code demo hoàn chỉnh trên:

 

 

Tổng kết

Ưu và nhược điểm

Hãy nói về ưu điểm trước, chắc cũng không khó nhận ra Observer Design Pattern cho phép chúng ta có thể xử lý nhiều hành động khác nhau cùng lúc khi một sự kiện xảy ra và đồng thời nó cũng góp phần nào duy trì tính nhất quán giữa các method với nhau

Tuy nhiên điều này cũng gây ra sự lỏng lẻo trong bộ code hơn khi việc thay đổi trạng thái của event hoặc action nào đó của Subject sẽ ảnh hưởng đến toàn bộ các Observer đang subscribe Subject đó. Nhưng không vì thế mà Observer Pattern không có ứng dụng trong thực tế, ví dụ nếu bạn có đang phát triển các ứng dụng sử dụng Redux và React Context thì chắc bạn không biết rằng chúng được implement dựa trên kiến trúc Observer Pattern.

Cuối cùng thì mong những kiến thức tôi chia sẻ trên đây sẽ mang đến cho người đọc thêm nhiều kiến thức về ngôn ngữ lập trình mình đang làm việc, càng biết nhiều thì càng tốt mà.

Cám ơn các bạn đã theo dõi bài viết!



 
Copyright© Đại học Duy Tân 2010 - 2024