Thursday, January 14, 2021

Những Patterns Core trong Java

Patterns Core trong Java

Gần đây, chúng tôi đã xem xét các Mẫu thiết kế sáng tạo và tìm chúng ở đâu trong JVM và các thư viện cốt lõi khác. Bây giờ chúng ta sẽ xem xét các Behaviroal Patterns. Những điều này tập trung vào cách các đối tượng của chúng ta tương tác với nhau hoặc cách chúng ta tương tác với chúng.

Những Patterns Core trong Java

Mẫu Chuỗi trách nhiệm cho phép các đối tượng triển khai một giao diện chung và cho mỗi quá trình triển khai có thể ủy quyền cho giao diện tiếp theo nếu thích hợp. Sau đó, điều này cho phép chúng tôi xây dựng một chuỗi triển khai, trong đó mỗi triển khai thực hiện một số hành động trước hoặc sau lệnh gọi đến phần tử tiếp theo trong chuỗi:

interface ChainOfResponsibility {

    void perform();

}

class LoggingChain {

    private ChainOfResponsibility delegate;


    public void perform() {

        System.out.println("Starting chain");

        delegate.perform();

        System.out.println("Ending chain");

    }

}

Ở đây, chúng ta có thể thấy một ví dụ trong đó việc triển khai của chúng ta được in ra trước và sau cuộc gọi ủy nhiệm.

Chúng tôi không bắt buộc phải kêu gọi người đại diện. Chúng tôi có thể quyết định rằng chúng tôi không nên làm như vậy và thay vào đó là chấm dứt chuỗi sớm. Ví dụ: nếu có một số tham số đầu vào, chúng tôi có thể đã xác thực chúng và kết thúc sớm nếu chúng không hợp lệ.

 Bộ lọc Servlet là một ví dụ từ hệ sinh thái JEE hoạt động theo cách này. Một cá thể duy nhất nhận được yêu cầu và phản hồi của servlet và một cá thể FilterChain đại diện cho toàn bộ chuỗi bộ lọc. Sau đó, mỗi người phải thực hiện công việc của mình và sau đó kết thúc chuỗi hoặc gọi chain.doFilter () để chuyển quyền kiểm soát cho bộ lọc tiếp theo:

public class AuthenticatingFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 

      throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;

        if (!"MyAuthToken".equals(httpRequest.getHeader("X-Auth-Token")) {

             return;

        }

        chain.doFilter(request, response);

    }

}

Mẫu lệnh cho phép chúng ta đóng gói một số hành vi cụ thể - hoặc lệnh - đằng sau một giao diện chung, để chúng có thể được kích hoạt chính xác trong thời gian chạy.

Thông thường, chúng ta sẽ có một giao diện Lệnh, một cá thể Bộ nhận nhận phiên bản lệnh và một Invoker chịu trách nhiệm gọi phiên bản lệnh chính xác. Sau đó, chúng tôi có thể xác định các phiên bản khác nhau của giao diện Command để thực hiện các hành động khác nhau trên bộ thu:

interface DoorCommand {

    perform(Door door);

}

class OpenDoorCommand implements DoorCommand {

    public void perform(Door door) {

        door.setState("open");

    }

}

Ở đây, chúng ta có một triển khai lệnh sẽ lấy một Cửa làm bộ nhận và sẽ làm cho cánh cửa trở nên “mở”. Kẻ xâm lược của chúng ta sau đó có thể gọi lệnh này khi nó muốn mở một cánh cửa nhất định và lệnh này tóm tắt cách thực hiện điều này.

Trong tương lai, chúng ta có thể cần phải thay đổi OpenDoorCommand của mình để kiểm tra xem cửa có bị khóa trước không. Thay đổi này sẽ hoàn toàn nằm trong lệnh và các lớp người nhận và người gọi không cần có bất kỳ thay đổi nào.

Một ví dụ rất phổ biến của mẫu này là lớp Hành động trong Swing:

Action saveAction = new SaveAction();

button = new JButton(saveAction)

Ở đây, SaveAction là lệnh, thành phần Swing JButton sử dụng lớp này là người gọi và việc triển khai Hành động được gọi với ActionEvent là người nhận.

Mẫu Iterator cho phép chúng tôi làm việc trên các phần tử trong một tập hợp và tương tác với từng phần tử lần lượt. Chúng tôi sử dụng điều này để viết các hàm sử dụng một trình lặp tùy ý trên một số phần tử mà không quan tâm đến việc chúng đến từ đâu. Nguồn có thể là một danh sách có thứ tự, một tập hợp không có thứ tự hoặc một luồng vô hạn:

void printAll<T>(Iterator<T> iter) {

    while (iter.hasNext()) {

        System.out.println(iter.next());

    }

}

Tất cả các tập hợp tiêu chuẩn JVM thực hiện mẫu lặp lại bằng cách hiển thị một phương thức iterator () trả về một for <T> trên các phần tử trong tập hợp. Các luồng cũng triển khai cùng một phương thức, ngoại trừ trong trường hợp này, nó có thể là một luồng vô hạn, vì vậy trình lặp có thể không bao giờ kết thúc.

Mẫu Memento cho phép chúng ta ghi các đối tượng có thể thay đổi trạng thái, sau đó hoàn nguyên về trạng thái trước đó của chúng. Về cơ bản là một chức năng "hoàn tác" cho trạng thái đối tượng.

Điều này có thể được thực hiện tương đối dễ dàng bằng cách lưu trữ trạng thái trước đó bất kỳ khi nào một bộ thiết lập được gọi

class Undoable {

    private String value;

    private String previous;


    public void setValue(String newValue) {

        this.previous = this.value;

        this.value = newValue;

    }


    public void restoreState() {

        if (this.previous != null) {

            this.value = this.previous;

            this.previous = null;

        }

    }

}


No comments:

Post a Comment