Tôi biết đây là một câu hỏi cũ, nhưng tôi nghĩ rằng tôi có một ví dụ thú vị khác mà tôi đã thực hiện gần đây.
Đây là một ví dụ rất thực tế về mô hình chiến lược đang được sử dụng trong hệ thống cung cấp tài liệu.
Tôi đã có một hệ thống phân phối PDF nhận được một kho lưu trữ chứa nhiều tài liệu và một số siêu dữ liệu. Dựa trên siêu dữ liệu, nó quyết định vị trí đặt tài liệu vào; nói, tùy thuộc vào dữ liệu, tôi có thể lưu trữ các tài liệu A
, B
hoặc C
hệ thống lưu trữ, hoặc một kết hợp của ba.
Các khách hàng khác nhau đã sử dụng hệ thống này và họ có các yêu cầu khôi phục / xử lý lỗi khác nhau trong trường hợp có lỗi: một người muốn hệ thống phân phối dừng ở lỗi đầu tiên, để lại tất cả tài liệu đã được giao trong kho của họ, nhưng dừng quá trình và không giao bất kỳ thứ gì khác ; một người khác muốn nó khôi phục B
trong trường hợp có lỗi khi lưu trữ C
, nhưng hãy để lại bất cứ thứ gì đã được giao cho A
. Thật dễ dàng để tưởng tượng rằng một thứ ba hoặc thứ tư cũng sẽ có những nhu cầu khác nhau.
Để giải quyết vấn đề, tôi đã tạo một lớp phân phối cơ bản có chứa logic phân phối, cùng với các phương thức để khôi phục nội dung từ tất cả các kho. Những phương pháp đó không thực sự được gọi bởi hệ thống phân phối trực tiếp trong trường hợp có lỗi. Thay vào đó, lớp này sử dụng Dependency Injection để nhận một lớp "Rollback / Error Xử lý Chiến lược" (dựa trên khách hàng sử dụng hệ thống), được gọi trong trường hợp có lỗi, lớp này sẽ gọi các phương thức rollback nếu nó phù hợp với chiến lược đó.
Bản thân lớp phân phối báo cáo những gì đang xảy ra với lớp chiến lược (tài liệu nào đã được chuyển đến kho nào và những lỗi nào đã xảy ra) và bất cứ khi nào có lỗi xảy ra, nó sẽ hỏi chiến lược có tiếp tục hay không. Nếu chiến lược cho biết "dừng nó", lớp này sẽ gọi phương thức "cleanUp" của chiến lược, phương thức này sử dụng thông tin được báo cáo trước đó để quyết định phương thức khôi phục nào cần gọi từ lớp phân phối hoặc đơn giản là không làm gì cả.
rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);
if (rollbackStrategy.mustAbort()) {
rollbackStrategy.rollback(); // rollback whatever is needed based on reports
return false;
}
Vì vậy, bây giờ tôi có hai chiến lược khác nhau: một là QuitterStrategy
(thoát khỏi lỗi đầu tiên và không xóa gì) và một là MaximizeDeliveryToAStrategy
(cố gắng hết sức có thể để không hủy bỏ quy trình và không bao giờ khôi phục nội dung được phân phối vào bộ nhớ A
, nhưng khôi phục nội dung B
nếu giao hàng C
không thành công).
Theo hiểu biết của tôi, đây là một ví dụ về mô hình chiến lược. Nếu bạn (có, bạn đang đọc) nghĩ tôi sai, hãy comment bên dưới cho tôi biết. Tôi tò mò không biết điều gì sẽ tạo nên cách sử dụng "thuần túy" của mẫu chiến lược và những khía cạnh nào trong việc triển khai của tôi vi phạm định nghĩa. Tôi nghĩ nó trông hơi buồn cười vì giao diện chiến lược hơi béo. Tất cả các ví dụ tôi đã thấy cho đến nay chỉ sử dụng một phương pháp, nhưng tôi vẫn nghĩ rằng điều này gói gọn một thuật toán (nếu một phần logic nghiệp vụ có thể được coi là một thuật toán, thì tôi nghĩ nó đúng).
Vì chiến lược cũng được thông báo về các sự kiện trong quá trình thực hiện phân phối, nó cũng có thể được coi là Người quan sát , nhưng đó là một câu chuyện khác.
Thực hiện một nghiên cứu nhỏ, có vẻ như đây là một "mẫu kết hợp" (giống như MVC, một mẫu sử dụng nhiều mẫu thiết kế bên dưới theo một cách cụ thể) được gọi là Cố vấn . Đó là một cố vấn về việc phân phối có nên tiếp tục hay không, nhưng nó cũng là một trình xử lý lỗi hoạt động vì nó có thể khôi phục nội dung khi được yêu cầu.
Tuy nhiên, đây là một ví dụ khá phức tạp có thể khiến bạn cảm thấy rằng cách sử dụng của mô hình chiến lược đều quá đơn giản / ngớ ngẩn. Nó có thể thực sự phức tạp và thậm chí có thể áp dụng hơn khi được sử dụng cùng với các mẫu khác.