Observer pattern là gì? – Nhất trụ kình thiên
Bài viết được sự cho phép của tác giả Kiên Nguyễn
Hôm rồi có đứa em đi phỏng vấn, câu hỏi về Observer Pattern. Không có gì để nói nếu tới cái “main content” của pattern này nó cũng không nắm được. BỨC XÚC QUÁ!
Ngồi viết bài này chia sẻ với các “chư vị đồng môn”. Thứ nhất là về Observer pattern, hai nữa là cách học một pattern, áp dụng thực tiễn. Một số ông vừa mới nghĩ tới Design Pattern thôi đã toát mồ hôi hột, đi phỏng vấn được hỏi câu hỏi về Design Pattern run cầm cập, trả lời ú ớ.
Nhưng thực chất người phỏng vấn không hề yêu cầu cao tới mức lên bảng cầm bút implement một design pattern hoàn chỉnh, cái người interview cần là cái concept của design pattern đó. Nắm được để biết trong tình huống (situatation) nào thì dùng pattern nào cho phù hợp. Còn lúc implement thì research, chả sao cả, gõ đúng keyword thôi.
Tại sao một Software Engineer tầm cỡ lại cần biết hết Design Pattern?. Vì nó là những mẫu thiết kế chuẩn mực đã được đúc kết từ trước, qua rất nhiều lần implement sai, những hệ thống “banh xa lông”, người ta mới rút ra được pattern đó.
1. Bắt đầu từ cái tên
Observer pattern – tách ra thành hai cái, ob và server. Ob ở đây là object (đối tượng). Còn server?, server ở đây là hướng về cái đối tượng trung tâm, ví như server. Mấy cái rìa rìa là client bên ngoài
Cũng là Behavior Pattern, nhắc tới là nhớ ngay cái pattern đó làm gì?, điển hình là cái Iterator Pattern – Đôi điều thú vị từ Kieblog. Nhìn cái chữ Iterator thôi là nhớ cái main content là loop, cái pattern này chắc chắn design ra để hỗ trỡ cái việc loop.
Đấy, chỉ cần nhớ cái concept vậy thôi là chả bao giờ sợ quên design pattern.
2. Định nghĩa về Observer pattern
Nhớ mãi không quên cái tên pattern rồi. Giờ đi vào detail, chứ nhớ không vậy thì cũng không ổn. Phải nắm rõ 2 thứ:
- Khi nào sử dụng?, sử dụng như thế nào?
- Điểm mạnh, điểm yếu
Observer Pattern là dạng pattern hành vi (Behavior Pattern). Định nghĩa:
Observer is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing.
Observer là pattern hành vi, giúp chúng ta xác định cơ chế đăng kí để thông báo tới nhiều object về bất kì sự kiện nào xảy ra với đối tượng mà chúng đang đăng kí
Hơn nữa, do là Behavior Pattern nên Observer là mối quan hệ one to many relationship. Một ông ở giữa trụ, một trụ chống trời!
2.1 Bài toán thực tế
Bài toán thực tế. Có 10 người trong một khu dân cứ muốn mua iPhone 12 ở cửa hàng trung tâm khu dân cư.
Nếu cửa hàng không có cơ chế gì thông báo qua phone, qua mail, mỗi người sẽ tới hỏi cửa hàng một vài lần. Câu trả lời là có, chưa có, có chưa có. Không ổn!
Nếu cửa hàng gửi thông báo cho tất cả 10 người về việc có iPhone mới?. Ổn, nhưng gửi thông báo iPhone 11 cho cả 10 người thì người ta chửi sml. Ông X giàu tổ bố, nên chỉ thích 12, 11 đ’ đủ tuổi. Ông Y mẹ bán vàng, gia cảnh nghèo hơn, chỉ thích 8 Plus, nên thông báo về 12 ổng cũng la bm.
Từ bài toán thực tế này (chém thế chứ méo biết có phải không), Observer Pattern ra đời. Chỉ gửi notification cho những người đăng kí quan sát đối tượng (Objects) đó, ngoài ra không gửi, không mang tiếng spam.
2.2 Hiện thực ý tưởng
Đã có ý tưởng thế, pattern này chia thành hai thành phần chính là Publisher và Subscribers
- Publisher: quản lý sự kiện mới (có notifi, có object mới). Sẽ publish thông tin đó ra cho subscribler.
- Subscribers: ông này thì dễ hiểu rồi, như subscribers Youtube (ấn chuông), khi nào có video mới thì nó bắn notification lên. Chuẩn bài dễ hiểu!
Chi tiết hơn nha.
Đầu tiên, thằng Publisher. Trong Observer Pattern thì thằng Thằng này có 3 method: đăng kí (subscribe), bỏ đăng kí (unsubscribe) và thông báo (notify).
// Source code: refactoring.guru - observer pattern public class EventManager { Map<String, List<EventListener>> listeners = new HashMap<>(); public EventManager(String... operations) { for (String operation : operations) { this.listeners.put(operation, new ArrayList<>()); } } public void subscribe(String eventType, EventListener listener) { List<EventListener> users = listeners.get(eventType); users.add(listener); } public void unsubscribe(String eventType, EventListener listener) { List<EventListener> users = listeners.get(eventType); users.remove(listener); } public void notify(String eventType, File file) { List<EventListener> users = listeners.get(eventType); for (EventListener listener : users) { listener.update(eventType, file); } } }
Thằng Subscriber chỉ là một interface, tất cả những thằng nào đăng kí với Publisher đều implement cái interface này.
// Source code: refactoring.guru - observer pattern package refactoring_guru.observer.example.listeners; import java.io.File; // Chỉ là interface, ông nào đăng kí thì implement interface này public interface EventListener { void update(String eventType, File file); }
The Subscriber interface declares the notification interface. In most cases, it consists of a single
update
method.Subscriber interface sẽ định nghĩa notification interface. Trong hầu hết các trường hợp, nó chỉ có duy nhất một method update.
Cuối cùng là ông Concrete Subscribers – ông này là người đăng kí cuối cùng. Ông này thì implement interface Subscribers. Ngoài ra còn override method update, tùy cơ ứng biến cho từng trường hợp. Khá linh động
// Source code: refactoring.guru - observer pattern public class EmailNotificationListener implements EventListener { private String email; public EmailNotificationListener(String email) { this.email = email; } // Override lại method update, tùy cơ ứng biến khi có thay đổi từ Publisher @Override public void update(String eventType, File file) { System.out.println("Email to " + email + ": Someone has performed " + eventType + " operation with the following file: " + file.getName()); } }
Ta cũng có ông Editor để implement các method sẽ gọi notify(), thông báo tới tất cả Subscriber
// Source code: refactoring.guru - observer pattern package refactoring_guru.observer.example.editor; import refactoring_guru.observer.example.publisher.EventManager; import java.io.File; public class Editor { public EventManager events; private File file; public Editor() { this.events = new EventManager("open", "save"); } // Actions method đăng kí gọi notify public void openFile(String filePath) { this.file = new File(filePath); events.notify("open", file); } // Actions method đăng kí gọi notify public void saveFile() throws Exception { if (this.file != null) { events.notify("save", file); } else { throw new Exception("Please open a file first."); } } }
Cuối cùng, main method chỉ việc đăng kí các event và gọi actions.
public class Demo { public static void main(String[] args) { Editor editor = new Editor(); // Đăng kí loại event và các actions muốn làm với event đó editor.events.subscribe("open", new LogOpenListener("/path/to/log/file.txt")); editor.events.subscribe("save", new EmailNotificationListener("[email protected]")); try { // Gọi tới notify để thông báo tới các subscriber editor.openFile("test.txt"); editor.saveFile(); } catch (Exception e) { e.printStackTrace(); } } }
3. Ưu nhược điểm
Ưu điểm lớn nhất ở Observer Pattern là khi có thay đổi ở Subscribler sẽ không ảnh hưởng tới Publisher. Cái này vô cùng quan trọng, mỗi channel trên Youtube đôi khi tới cả triệu lượt theo dõi.
Nếu một thay đổi ở Subscriber đều cần update tới Publisher thì toang, toang thật sự.
Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher’s code.
Có thể thêm mới một class subscriber mà không cần phải thay đổi gì code ở publisher.
Ngoài ra
You can establish relations between objects at runtime.
Với pattern này, ta còn có thể khởi tạo mối liên hệ giữa các object trong lúc runtime
4. Tham khảo
Đối với Java, trên Java 9 có thể sử dụng java.util.Observer
. Trên Python thì sử dụng thông qua Pip pip install pattern-observer
.
Bài viết gốc được đăng tải tại kieblog.vn
Có thể bạn quan tâm:
- Mediator Design Pattern – Collaborate via me
- Repository design pattern hoàn thiện trong Laravel
- React Pattern: Tập trung PropTypes
Xem thêm Việc làm Developer hấp dẫn trên TopDev
- B BenQ RD Series – Dòng Màn Hình Lập Trình 4k+ Đầu Tiên Trên Thế Giới
- i iOS 18 có gì mới? Có nên cập nhật iOS 18 cho iPhone của bạn?
- G Gamma AI là gì? Cách tạo slide chuyên nghiệp chỉ trong vài phút
- P Power BI là gì? Vì sao doanh nghiệp nên sử dụng PBI?
- K KICC HCMC x TOPDEV – Bước đệm nâng tầm sự nghiệp cho nhân tài IT Việt Nam
- T Trello là gì? Cách sử dụng Trello để quản lý công việc
- T TOP 10 SỰ KIỆN CÔNG NGHỆ THƯỜNG NIÊN KHÔNG NÊN BỎ LỠ
- T Tìm hiểu Laptop AI – So sánh Laptop AI với Laptop thường
- M MySQL vs MS SQL Server: Phân biệt hai RDBMS phổ biến nhất
- S SearchGPT là gì? Công cụ tìm kiếm mới có thể đánh bại Google?