策略模式

/ 设计模式

策略模式(Strategy)

定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。策略模式使得算法可独立于使用它的客户而变化

GoF23种设计模式中,属于行为型模式( Behavioral Patterns)

策略模式将不同的算法聚合起来,提供了统一的策略接口。将策略的选择权交给客户端动态选择,

实例

策略模式总览

角色说明

举例

以打折活动为例。两家店铺进行打折,一家打折策略是全场85折,另一家是满300减120。

角色说明

策略模式举例

code

public interface DiscountStrategy {
    void  doStrategy();
}
public class Discount85 implements DiscountStrategy{


    @Override
    public void doStrategy() {
        System.out.println("打折啦,全场85折!!!");
    }
}
public class Full300Reduce120 implements DiscountStrategy{
    @Override
    public void doStrategy() {
        System.out.println("打折啦,满300减120!!!");
    }
}
public class DiscountActivity {

    private DiscountStrategy discountStrategy;

    public DiscountActivity(DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }

    public void doActivity() {
        discountStrategy.doStrategy();
    }
}
public class Client {
    public static void main(String[] args) {
        DiscountActivity discountActivity;

        System.out.println("店铺A:");
        discountActivity = new DiscountActivity(new Discount85());
        discountActivity.doActivity();

        System.out.println("店铺B:");
        discountActivity = new DiscountActivity(new Full300Reduce120());
        discountActivity.doActivity();
    }
}
店铺A:
打折啦,全场85折!!!
店铺B:
打折啦,满300减120!!!

思考

这里的店铺A、店铺B实际开发中应该都是接口处动态传参过来的。客户端要决定使用那种策略还需要if-else判断。

因此,避免多重判断,我们可以使用简单工程模式,建立工厂时,我们还可以通过单例模式和享元模式静态初始化所有具体策略类。

如果不想手写静态初始化代码,我们还可以通过Spring 动态扫描接口实现类,实现动态加载,具体操作如下。

Map<String, DiscountStrategy> map = SpringContextHolder.getApplicationContext().getBeansOfType(DiscountStrategy.class);
public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        synchronized (SpringContextHolder.class) {
            SpringContextHolder.applicationContext = applicationContext;
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        return applicationContext.getBean(clazz);
    }

    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("applicaitonContext未注入,请在application-context.xml中定义SpringContextHolder");
        }
    }

}

实例

code:com.google.common.hash.BloomFilterStrategies

角色说明

该处策略模式采用了枚举单例模式,布隆过滤器的具体实现打算以后再详看。

补充:Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。

总结

策略模式是日常开发中最为常见的模式。可简单理解为接口的封装与使用。需要注意的是,策略模式与其他模式的结合使用,如:工厂模式、享元模式等。