2014-10-26 19 views
7

Tôi đã đọc các trao đổi ngăn xếp trước đó về thay thế logic điều kiện trong Java như IF/ELSE với các mẫu Chiến lược/Nhà nước. thay thế. Dưới đây là cùng tôi nhìn - Long list of if statements in JavaConverting many 'if else' statements to a cleaner approachThay thế if/else logic bằng mẫu trạng thái/chiến lược

tôi về cơ bản đang viết một quản lý tập tin tải về và đây là tôi IF/ELSE xây dựng:

  1. Nếu tập tin và đó là file zip tồn tại sau đó di chuyển file zip để nén thư mục tệp và đọc trong tệp
  2. Nếu tệp zip tồn tại, sau đó giải nén tệp và di chuyển tệp zip vào thư mục tệp zip và đọc trong tệp
  3. Nếu tệp zip không tồn tại, hãy tải xuống từ URL được chỉ định và sau đó giải nén và đọc và di chuyển tệp zip vào thư mục được chỉ định.
  4. Nếu tệp zip không tồn tại trong URL, hãy tạo tệp trống và ghi nó ra đĩa.

Về cơ bản, tôi hiểu rằng bạn đặt bốn điều kiện này làm khóa trong bản đồ đã băm rồi giá trị là "Lệnh" cần được phát hành. Tuy nhiên tôi tin rằng bạn vẫn cần một If/Else để quyết định hành động nào được gọi trên khóa được đưa ra làm đầu vào. Vì vậy, tôi không thấy lợi ích. Ai đó có thể giải thích?

Trả lời

4

Tôi nghĩ bạn nên sử dụng mẫu GoF Chain of responsibility. Bạn nên giới thiệu hai giao diện: 1) Condition nơi bạn sẽ kiểm tra điều kiện thích hợp, ví dụ: "Nếu tệp zip không tồn tại" và trả về kết quả boolean - "true" nếu điều kiện được thỏa mãn, nếu không "else", 2) Execution strategy, sẽ chạy hành động được gán với điều kiện, ví dụ: "tải xuống từ URL được chỉ định và sau đó giải nén nó và đọc trong tệp và di chuyển tệp zip vào thư mục được chỉ định". Vì vậy, giao diện thứ nhất sẽ trả lời cho câu hỏi "khi", và thứ hai - "sau đó". Triển khai "Điều kiện" và triển khai "thực hiện chiến lược" nên được kết hợp thành "tuple" (hoặc cặp, mục nhập, v.v.). Bộ "tuple" này sẽ được chuyển đến bộ sưu tập theo thứ tự mà bạn đã mô tả. Sau đó, khi bạn cần xử lý tệp zip, bạn sẽ lặp qua bộ sưu tập, gọi điều kiện và kiểm tra kết quả, nếu kết quả là "true", sau đó gọi "chiến lược thực thi" thích hợp. Ngoài ra, điều kiện có thể được kết hợp với chiến lược thực hiện và chuyển sang giao diện/triển khai đơn lẻ với hai phương pháp. Bối cảnh, sẽ mô tả trạng thái hiện tại của tệp zip có thể được chuyển giữa các điều kiện/chiến lược thực hiện. Hy vọng điều này sẽ hữu ích.

Cập nhật. Ví dụ về mã (bằng Java).

/** 
* All implementations should check proper condition 
*/ 
interface Condition { 

    /** 
    * Check if condition is satisfied 
    * 
    * @param pathToFile path to target file 
    * @return 'true' if condition is satisfied, otherwise 'false' 
    */ 
    boolean isSatisfied(String pathToFile); //i've made an assumption that you'll manipulate file path for checking file 
} 
... 
/** 
* Childs will wrap some portion of code (if you'll use language, that supports lambdas/functors, this interface/implementation can be replaced with lambda/functor) 
*/ 
interface Action { 

    /** 
    * Execute some portion of code 
    * 
    * @param pathToFile path to target file 
    */ 
    void execute(String pathToFile); 
} 
... 
class ZipFileExistsCondition implements Condition { 

    @Override 
    public boolean isSatisfied(String pathToFile) { 
    ... //check if zip file exists 
    } 
} 
... 
class ZipFileDoesNotExists implements Condition { 
    @Override 
    public boolean isSatisfied(String pathToFile) { 
    ... //download zip file and move it to some temp directory 
    //if file downloaded ok, than return 'true' otherwise 'false' 
    } 
} 
... 
class AlwaysSatisfiedCondition implements Condition { 
    @Override 
    public boolean isSatisfied(String pathToFile) { 
    ... //always returns 'true', to run action assigned with this condition 
    } 
} 
... 
Collection<Map.Entry<Condition, Action>> steps = Arrays.asList(
new AbstractMap.ImmutableEntry<Condition, Action>(new ZipFileExistsCondition(), 
new Action() { /*move zip file to zip file directory and read in file*/ }), 
new ZipFileDoesNotExists(), new Action() { /*download it from specified URL and then unzip it and read in file and move zip file to specified directory*/ }, 
new AlwaysSatisfiedCondition(), new Action() { /*create blank file and write it out to disk*/ } 
); 
... 
String pathToFile = ... 
... 
for(Map.Entry<Condition, Action> step: steps) { 
if(!step.getKey().isSatisfied(pathToFile)) 
    continue; 

step.getValue().execute(pathToFile); 
} 

Ghi chú: 1), bạn có thể thực hiện 'Điều kiện' như các lớp học mang tính chất 2) 'AlwaysSatisfiedCondition' có thể là singleton, 3) nếu bạn đang sử dụng Java/Groovy/Scala, bạn có thể sử dụng ổi/Apache Commons 'Predicate' thay vì 'Condition', 'Function' hoặc 'Closure' thay vì 'Action'.

Nếu bạn cần thoát sau điều kiện 'hài lòng' đầu tiên và thực hiện hành động thích hợp thì chỉ cần đặt 'break'/'return' sau khi thực thi hành động.

+0

Cảm ơn phản hồi đó. Khi tôi hiểu câu trả lời của bạn, bạn muốn tôi lặp lại một bộ sưu tập và sau đó tạo một câu lệnh if để xem chiến lược nào cần được thực hiện đúng không? – gansub

+0

Không. Bạn nên lặp lại quá trình thu thập và yêu cầu từng "điều kiện.không hài lòng", vì vậy sẽ không có bất kỳ câu lệnh "if/then/else" nào khác, nhưng mọi "điều kiện" sẽ bao gồm câu lệnh "if". – nndru

+0

Tuyệt. Vì vậy, điểm then chốt ở đây là "Thứ tự" để lặp lại. Một khi lệnh được cố định thì nó đơn giản. Vì vậy, chỉ cho rõ ràng hơn tôi có FileReadCondition mà thực hiện điều kiện và FileReadExecution mà thực hiện Execution. FileReadCondition có được ủy quyền cho FileReadExecution không? Có lẽ một số mã sẽ giúp. – gansub

1

Sau đây là cách thích hợp để biên dịch mã này. Điểm mấu chốt ở đây là AbstractMap.SimpleImmutableEntry là một mục duy nhất. Nếu bạn muốn thêm nhiều mục hơn thì bạn cần phải khởi tạo lớp cho mỗi mục nhập.

Collection<Map.Entry<Condition,Action>> steps = Arrays.asList 
    (
    (new AbstractMap.SimpleImmutableEntry<Condition,Action> 
     (new FileExistsCondition(), 
     new Action() 
     { 
     public void execute(String pathToFile){System.out.println("the path to file is srtm " + pathToFile);} 
     } 
     ) 
    ), 
    (new AbstractMap.SimpleImmutableEntry<Condition,Action> 
     (new ZipFileExistsCondition(), 
     new Action() 
     { 
     public void execute(String pathToFile){System.out.println("the path to file is " + pathToFile);} 
     } 
     ) 
    ), 
    (new AbstractMap.SimpleImmutableEntry<Condition,Action> 
     (new ZipFileDoesNotExistCondition(), 
     new Action() 
     { 
     public void execute(String pathToFile){System.out.println("the path to file is " + pathToFile);} 
     } 
    ) 
    ) 
    ); 
Các vấn đề liên quan