Mẫu thiết kế chiến lược đã sửa đổi


11

Gần đây tôi đã bắt đầu xem xét các Mẫu thiết kế và một điều tôi đang viết mã sẽ phù hợp hoàn hảo với mẫu Chiến lược, ngoại trừ một khác biệt nhỏ.

Về cơ bản, một số (nhưng không phải tất cả) các thuật toán của tôi, cần một tham số phụ hoặc hai được truyền cho chúng.

Vì vậy, tôi sẽ cần phải

  • truyền cho họ một tham số phụ khi tôi gọi phương thức tính toán của họ

hoặc là

  • lưu trữ chúng dưới dạng các biến trong lớp ConcreteAlerskym và có thể cập nhật chúng trước khi tôi gọi thuật toán.

Có một mẫu thiết kế cho nhu cầu này không / Làm cách nào tôi có thể thực hiện điều này trong khi bám sát Mẫu chiến lược?

Tôi đã xem xét chuyển đối tượng khách cho tất cả các thuật toán và lưu trữ các biến trong đó, sau đó chỉ sử dụng khi thuật toán cụ thể cần. Tuy nhiên, tôi nghĩ rằng điều này vừa khó sử dụng, vừa đánh bại điểm của mô hình chiến lược.

Để rõ ràng tôi đang triển khai trong Java và do đó, không có sự sang trọng của các tham số tùy chọn (sẽ giải quyết điều này một cách độc đáo).


Các tham số tùy chọn như trong C ++ sẽ không giải quyết được gì, vì chúng chỉ là một tốc ký để xác định nhiều phương thức quá tải.
maaartinus

Tôi sẽ cố gắng hết sức để tránh lưu trữ các tham số bổ sung ở đâu đó mà tôi phải thay đổi chúng trước khi sử dụng. Bằng cách này, bạn làm cho ConcreteAlacticm có trạng thái, vì vậy nó không thể được chuyển dễ dàng sang các phương thức hoặc luồng khác. Hơn nữa, thật dễ dàng để quên thiết lập các tham số.
maaartinus

Câu trả lời:


5

Samuel, có thể gói gọn tham số mà mỗi chiến lược đưa vào một lớp chung và sau đó mở rộng lớp Thông số chung đó để thêm nhiều hành vi mà một số chiến lược của bạn cần cụ thể không?

Ví dụ

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

Và sau đó, xác định hệ thống phân cấp chiến lược như:

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

gọi chiến lược trên là: myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

gọi chiến lược trên bằng cách truyền SpecialStrategyParameterví dụ thay vì:mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

Vui lòng cập nhật nếu có gì không rõ ràng. Sẽ vui vẻ giải thích / làm rõ.


1
-1 yêu cầu downcast, phá vỡ đóng gói của thiết kế. Mặc dù đó là một cải tiến về thiết kế trong câu hỏi, có nhiều cách tốt hơn để lột da con mèo này.
Tallseth

@tallseth Mình thấy downcast quá. Nhưng tôi không thấy những cách tốt hơn. Bạn có thể vui lòng chỉ ra một giải pháp tốt hơn? Một bài báo hay cái gì đó?
Narek

Trên thực tế, có. @ Jordão có câu trả lời tôi muốn, dựa trên các chi tiết chúng tôi có trong câu hỏi. Câu trả lời đó đóng vai trò là điểm mạnh của mô hình chiến lược. Nếu chúng ta đi theo cách tiếp cận trong câu trả lời này, tôi sẽ muốn StrategyParameterchứa tất cả các thông số có thể, giống như một DTO. Một số thực hiện chiến lược có thể bỏ qua chúng. Trong một số trường hợp, đó là cách tiếp cận tốt nhất. Bối cảnh là vua cho các loại vấn đề.
Tallseth

3

Bạn cần làm rõ chiến lược của bạn .

Tất cả phụ thuộc vào cách bạn sử dụng thuật toán của bạn. Để lớp khách hàng của bạn sử dụng các triển khai chiến lược khác nhau thay thế cho nhau, tất cả chúng cần phải có một sự trừu tượng hóa chung . Nếu chúng không theo cùng một giao diện, có thể thứ bạn cần là những thứ trừu tượng khác nhau .

Tôi đã sử dụng các chiến lược có thể định cấu hình trước đây, nơi bạn tham số hóa các lớp cụ thể khi xây dựng:

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

Bây giờ, ai đó vẫn cần tạo một thể hiện của lớp này và chuyển nó cho khách hàng của bạn. Nhưng khách hàng của bạn vẫn chỉ cần biết về Strategygiao diện.

Nó cũng hoạt động nếu phương thức chiến lược của bạn có các tham số, nhưng sau đó khách hàng của bạn biết về các tham số đó và chuyển chúng cho tất cả các triển khai mà nó hoạt động.


Máy khách là một trong những bối cảnh để cung cấp tham số.
andyczerwonka

1

Miễn là chữ ký được xác định rõ ràng trên giao diện, nó vẫn tuân thủ mẫu Chiến lược.

Các mẫu như được viết là hình thức đơn giản tuyệt đối nhất vẫn thể hiện hành vi dự kiến, vì vậy bạn có thể tô điểm chúng miễn là bạn giữ nguyên ý định ban đầu. Điều đó tất nhiên là giả sử bạn muốn theo mô hình. Không có điểm nào sử dụng một mẫu nếu nó không phù hợp, hoặc chỉ vì nó ở đó, nhưng trong trường hợp của bạn tôi nghĩ bạn ổn.


0

mở rộng dựa trên câu trả lời trên được cung cấp bởi đỉnh - bạn có thể sử dụng tính trừu tượng. Tôi đang sử dụng mã của đỉnh ở đây -

Giao diện MyStrargety { trừu tượng void myStrargetyMethod (tham số StrategParameter); }

class MyN normalStrargety mở rộng MyStrargety {ghi đè công khai void myStrargetyMethod (tham số StrategParameter) {// triển khai logic tại đây}}

class MyecializedStrargety mở rộng MyStrargety {ghi đè công khai void myStrargetyMethod (tham số StrategParameter, ExtraStrargetyParameter ExtraParameter) {// triển khai logic tại đây} }

Nếu tôi hiểu chính xác câu hỏi của bạn, bạn muốn chuyển một tham số phụ cho các thuật toán nhất định phải không? Xin vui lòng cho tôi biết nếu đây là những gì bạn đang tìm kiếm?


0

Nếu bạn xem cuốn sách Các mẫu thiết kế, sẽ không có gì sai khi một số SimpleStrargety tồn tại sử dụng ít hoặc không có tham số nào được thông qua, hoặc các tham số là một số nhân một kích thước phù hợp với tất cả / ít phổ biến nhất. Sự lựa chọn thiết kế ở đây là liệu điều này có làm bạn tổn thương về mặt xử lý thêm mà cuối cùng không được sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.