Java列舉的策略設計模式 -DEV

banq發表於2020-10-07

策略模式是一種GoF設計模式,允許軟體在執行時從一系列演算法中選擇一種。每種演算法都在自己的類中實現,這使得它們的客戶端可以互換。使用策略設計模式,類可以以不同的方式和不同的實現來執行相同的方法。這是Gamma等人在“設計模式”一書中的模式之一
例如,考慮需要通勤的工人。他可以使用不同的策略,例如乘汽車,摩托車,腳踏車或地鐵去。班級worker有一個領域transport。並且transport有方法commute。與演算法的類Car,Motorcycle,Bicycle,和Metro。他們需要實現Transport介面。
該方法的呼叫worker.transport.commute可以使用不同的演算法,即不同的策略。注意,上下文不負責選擇合適的演算法。這是由選擇一種策略的客戶端完成的。上下文只是從一種策略中執行該方法。因此,上下文獨立於實現。
在本文中,我們將使用Java列舉實現策略設計模式。列舉具有比大多數程式設計師所知道的更多的功能。
一旦這種方法稍微違反了開放-封閉原則,就會對此提出批評。使用列舉不能在執行時新增新的實現。您應該更新程式碼。讓我們看一下程式碼。
 

驗證器策略模式
第一個示例是XML,JSON,YAML或CSV內容的檔案格式驗證器。在傳統的Strategy實施中,您需要多個類,每種演算法一個。使用列舉,您可以在每個常量中實施業務規則。

public enum ValidatorStrategy {

    XML {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a XML content");
        }
    },
    JSON {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a JSON content");
        }
    },
    YAML {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a YAML content");
        }
    },
    CSV {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a CSV content");
        }
    };

    abstract void doValidation(String content);

}

上下文類從客戶端接收策略,並在所選策略中執行演算法。

public class ValidatorContext {

    private ValidatorStrategy strategy;

    public ValidatorContext(ValidatorStrategy strategy) {
        this.strategy = strategy;
    }

    public void setValidator(ValidatorStrategy validator) {
        this.strategy = validator;
    }

    public void runValidation(String content) {
        strategy.doValidation(content);
    }

}

最後一個元件是將驗證策略傳遞到上下文的客戶端。看到您validator.runValidation在設定策略後總是呼叫方法。

ValidatorContext validator = new ValidatorContext(ValidatorStrategy.XML);
validator.runValidation("XML content");

validator.setValidator(ValidatorStrategy.YAML);
validator.runValidation("YAML content");

validator.setValidator(ValidatorStrategy.JSON);
validator.runValidation("JSON content");

 

日期格式化策略模式
這是策略設計模式的另一個示例。現在,我們有了一個更復雜的情況,上下文類會將實現傳遞給策略類。這樣,可以使用像Spring這樣的依賴注入引擎。

public enum DateFormatterStrategy {
    BRAZIL {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatBrazil(date);
        }
    },
    BELGIUM {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatBelgium(date);
        }
    },
    US {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatUS(date);
        }
    };

    public abstract String doFormat(DateFormatterImpl formatter, Date date);

}

實現類如下所示。它包含用於格式化每個國家/地區的日期的業務規則。

public class DateFormatterImpl {

    private SimpleDateFormat sdfBrasil = new SimpleDateFormat("dd/MM/yyyy");
    private SimpleDateFormat sdfBelgium = new SimpleDateFormat("dd.MM.yyyy");
    private SimpleDateFormat sdfUS = new SimpleDateFormat("MM/dd/yyyy");

    public String formatBrazil(Date date) {
        return this.sdfBrasil.format(date);
    }

    public String formatBelgium(Date date) {
        return this.sdfBelgium.format(date);
    }

    public String formatUS(Date date) {
        return this.sdfUS.format(date);
    }

}

上下文類與之前看到的完全相同。我的意思是,它沒有任何明顯的區別。

public class DateFormatterContext {

    private DateFormatterStrategy strategy;
    private DateFormatterImpl formatter = new DateFormatterImpl();

    public DateFormatterContext(DateFormatterStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(DateFormatterStrategy strategy) {
        this.strategy = strategy;
    }

    public String format(Date date) {
        return this.strategy.doFormat(formatter, date);
    }

}

最後一個客戶端類與上一個客戶端類非常相似。設定策略後,執行方法formatter.format,然後所選策略將執行正確的演算法。

Date date = new Date();
DateFormatterContext formatter = new DateFormatterContext(DateFormatterStrategy.BELGIUM);
System.out.println("Belgium: " + formatter.format(date));

formatter.setStrategy(DateFormatterStrategy.BRAZIL);
System.out.println("Brazil: " + formatter.format(date));

formatter.setStrategy(DateFormatterStrategy.US);
System.out.println("US: " + formatter.format(date));


結論
Java Enum是一種方便的特殊型別,具有高階功能,可以幫助程式設計師滿足不同的需求。在這種情況下,我們與他們一起實施了戰略設計模式。這種方法具有優點,例如簡單性和較少的類。但是也有弊端,最值得注意的是它稍微打破了開放-封閉原則。



 

相關文章