Java枚举的策略设计模式 -DEV


策略模式是一种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是一种方便的特殊类型,具有高级功能,可以帮助程序员满足不同的需求。在这种情况下,我们与他们一起实施了战略设计模式。这种方法具有优点,例如简单性和较少的类。但是也有弊端,最值得注意的是它稍微打破了开放-封闭原则。