2016-10-09 29 views
10

Đây là câu hỏi thiết kế liên quan đến việc thực hiện Đường ống. Sau đây là triển khai ngây thơ của tôi.Thực hiện mẫu thiết kế đường ống

Giao diện cho bước cá nhân/công đoạn trong các đường ống:

public interface Step<T, U> { 
    public U execute(T input); 
} 

triển khai bê tông các bước/giai đoạn trong đường ống:

public class StepOne implements Step<Integer, Integer> { 
    @Override 
    public Integer execute(Integer input) { 
     return input + 100; 
    } 
} 

public class StepTwo implements Step<Integer, Integer> { 
    @Override 
    public Integer execute(Integer input) { 
     return input + 500; 
    } 
} 

public class StepThree implements Step<Integer, String> { 
    @Override 
    public String execute(Integer input) { 
     return "The final amount is " + input; 
    } 
} 

Lớp đường ống sẽ giữ/đăng ký các bước trong đường ống và thực hiện chúng sau cái khác:

public class Pipeline { 
    private List<Step> pipelineSteps = new ArrayList<>(); 
    private Object firstStepInput = 100; 

    public void addStep(Step step) { 
     pipelineSteps.add(step); 
    } 

    public void execute() { 
     for (Step step : pipelineSteps) { 
      Object out = step.execute(firstStepInput); 
      firstStepInput = out; 
     } 
    } 
} 

Diver program to execu te the pipeline:

public class Main { 
    public static void main(String[] args) { 
     Pipeline pipeline = new Pipeline(); 
     pipeline.addStep(new StepOne()); 
     pipeline.addStep(new StepTwo()); 
     pipeline.addStep(new StepThree()); 

     pipeline.execute(); 
    } 
} 

Tuy nhiên, bạn có thể thấy việc triển khai ngây thơ có nhiều hạn chế.

Một trong những điều quan trọng là vì yêu cầu là đầu ra của mỗi bước có thể thuộc bất kỳ loại nào, việc triển khai ngây thơ không an toàn kiểu (phương thức thực hiện trong lớp Pipeline). Nếu tôi tình cờ kết nối các bước trong đường ống không chính xác, ứng dụng sẽ không thành công.

Bất cứ ai có thể giúp tôi thiết kế giải pháp bằng cách thêm vào những gì tôi đã mã hóa hay chỉ cho tôi một mẫu đã có để giải quyết vấn đề này?

+1

[câu hỏi này] (http://stackoverflow.com/questions/5686332/pipeline-pattern-implementation-in-java) liên kết đến [tài liệu này] (http://parlab.eecs.berkeley.edu/wiki/_media/patterns/pipeline-v1.pdf) tham chiếu đến các mẫu. –

+0

Cảm ơn bạn @NickBell vì đã trỏ tới bài báo. Tuy nhiên, thông qua bài báo, tôi không thể hiểu cách thức các đường ống có thể được thiết kế để nó có thể xử lý các giai đoạn/bước với các loại đầu ra khác nhau. –

+2

Tôi sẽ cân nhắc xem xét [Java 1.8+ stream] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html) khi chúng cung cấp [chức năng] (https://docs.oracle.com/javase/tutorial/collections/streams/)/[doc's] (http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams- 2177646.html) vào ví dụ bạn đã nêu. Xem tại đây cho [duplicate] (http://stackoverflow.com/questions/8680610/java-generics-chaining-together-generic-function-object) –

Trả lời

6

tôi sẽ tập trung vào

Nếu tôi xảy ra để dây các bước trong đường ống không đúng cách, ứng dụng sẽ thất bại.

Vâng, đây là vấn đề. StepThree là người lạ ở đây. Tôi không nghĩ rằng một mô hình đơn giản có thể giúp đỡ, tôi nghĩ rằng nó phải là một sự kết hợp của chiến lược và xây dựng mô hình. Bằng ví dụ:

Pipeline<Integer,Integer> intPipe = new Pipeline<>(); 
intPipe = intPipe.add(new StepOne()); // increment 100 
intPipe = intPipe.add(new StepTwo()); // increment 500 
Pipeline<String, Integer> strPipe = intPipe.add(new StepThree()); // convert 

Whereat Pipeline là như thế này:

public static class Pipeline<IN, OUT> { 
    //... 
    public<A> Pipeline<OUT,A> add(Step<IN,A> step) { 
    pipelineSteps.add(step); 
    return (Pipeline<OUT,A>)this; 
    } 
} 

Sử dụng-builder-cú pháp nhanh này có thể làm việc:

Pipeline<String, Integer> pipe = new Pipeline<Integer, Integer>() 
    .add(new StepOne()).add(new StepTwo()).add(new StepThree()); 

này nên làm việc kể từ Generics không nằm trong bytecode.

+0

Cảm ơn Peter đã trả lời câu hỏi! :) –

+0

@PrashantChauhan tại dịch vụ của bạn, D –

2

Cách tiếp cận của bạn khá tốt. Tuy nhiên, tôi muốn mã lớp đường ống như thế này:

public class Pipeline { 
    private List<Step> pipelineSteps = new ArrayList<>(); 
    private Object firstStepInput = 100; 

    public Pipeline() { 
     pipelineSteps.add(new StepOne()); 
     pipelineSteps.add(new StepTwo()); 
     pipelineSteps.add(new StepThree()); 
    } 

    public void execute() { 
     for (Step step : pipelineSteps) { 
      Object out = step.execute(firstStepInput); 
      firstStepInput = out; 
     } 
    } 

    public String getResult() { 
     return (String) firstStepInput; 
    } 
} 

Bằng cách này, tất cả các kiến ​​thức bước cụ thể được đóng gói trong lớp đường ống.

Trong trường hợp này, phương thức thực thi có thể thực hiện vòng lặp. Tuy nhiên, lớp thực hiện có thể thực hiện từng bước một, nếu cần thiết.

+0

Cảm ơn bạn đã chỉ ra cách đóng gói chính xác lớp Pipeline. –

2

tại sao bạn cần thêm lớp học Pipeline? Tôi nghĩ bạn có thể loại bỏ người đàn ông trung gian.điều này sẽ làm cho api của bạn đơn giản, ví dụ:

Step<Integer, String> source = Step.of(Object::toString); 
Step<Integer, Integer> toHex = source.pipe(it -> Integer.parseInt(it, 16)); 

toHex.execute(11/*0x11*/);// return 17; 

bạn có thể thực hiện mô hình đường ống của bạn chỉ đơn giản là trong như sau:

interface Step<I, O> { 

    O execute(I value); 

    default <R> Step<I, R> pipe(Step<O, R> source) { 
     return value -> source.execute(execute(value)); 
    } 

    static <I, O> Step<I, O> of(Step<I, O> source) { 
     return source; 
    } 
} 

trong phiên bản java trước khi bạn có thể sử dụng một lớp trừu tượng thay vì:

abstract static class Step<I, O> { 

    public abstract O execute(I value); 

    public <R> Step<I, R> pipe(Step<O, R> source) { 
     return new Step<I, R>() { 
      @Override 
      public R execute(I value) { 
       return source.execute(Step.this.execute(value)); 
      } 
     }; 
    } 

    public static <I, O> Step<I, O> of(Step<I, O> source) { 
     return source; 
    } 
} 
+0

Bởi decents, underrated answer! –

0

public class Pipeline {

private List<Step> pipelineSteps = new ArrayList<>(); 
private Object firstStepInput = 100; 

public Pipeline() { 
    pipelineSteps.add(new StepOne()); 
    pipelineSteps.add(new StepTwo()); 
    pipelineSteps.add(new StepThree()); 

}

+0

Vui lòng định dạng (có một cửa sổ xem trước khi bạn viết câu trả lời của bạn) & ** giải thích ** câu trả lời của bạn. Bạn muốn mọi người hiểu những gì bạn đã làm, phải không? – Rafalon

Các vấn đề liên quan