设计模式之策略模式

策略模式

定义: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。

策略模式被广泛使用
(1)如redis淘汰策略,ttl 从已设置过期时间的数据集中挑选将要过期的数据淘汰,lru从已设置过期时间的数据集中挑选最近最少使用的数据淘汰,可以通过策略模式动态设置淘汰算法。
(2)如文件排序,根据文件大小,使用文件排序,内部并发文件排序,或者mapreduce排序。
既可以使得代码低耦合高内聚,又可以减少代码的if…else冗杂分支。

完整的策略模式应该包括策略的定义、策略的创建和策略的使用
代码演示1 缓存淘汰,使用不同算法指定缓存淘汰策略
策略定义
public interface EvictionStrategy {
    void evict();
}
策略创建
public class ConcreteEvictionStrategyA implements EvictionStrategy {
    @Override
    public void evict() {

    }
}

public class ConcreteEvictionStrategyB implements EvictionStrategy {
    @Override
    public void evict() {
        
    }
}

public class EvictionStrategyFactory {
    private static final Map<String, EvictionStrategy> strategies = new HashMap<>();

    static {
        strategies.put("A", new ConcreteEvictionStrategyA());
        strategies.put("B", new ConcreteEvictionStrategyB());
    }

    public static EvictionStrategy getStrategy(String type) {
        if (type == null || type.isEmpty()) {
            throw new IllegalArgumentException("type should not be empty");
        }
        return strategies.get(type);
    }
}
策略使用
public class UserCache {
    private Map<String, User> cacheData = new HashMap<>();
    private EvictionStrategy evictionStrategy;

    public UserCache(EvictionStrategy evictionStrategy) {
        this.evictionStrategy = evictionStrategy;
    }
}

public class Application {
    public static void main(String[] args) throws IOException {
        EvictionStrategy evictionStrategy = null;
        Properties properties = new Properties();
        properties.load(new FileInputStream("./config.properties"));
        String type = properties.getProperty("eviction_type");
        evictionStrategy = EvictionStrategyFactory.getStrategy(type);

        //运行时动态确定,根据配置文件的配置决定使用哪种策略
        UserCache userCache = new UserCache(evictionStrategy);

    }
}
代码演示2 文件内容排序,按照文件大小,选择不同策略排序
策略定义
public interface ISortAlg {
    void sort(String filePath);
}
策略创建
public class QuickSort implements ISortAlg {
    @Override
    public void sort(String filePath) {

    }
}

public class ExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {

    }
}

public class ConcurrentExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {

    }
}

public class MapReduceSort implements ISortAlg {
    @Override
    public void sort(String filePath) {

    }
}

public class SortAlgFactory {
    private static final Map<String, ISortAlg> sortAlgs = new HashMap<>();

    static {
        sortAlgs.put("QuickSort", (ISortAlg) new QuickSort());
        sortAlgs.put("ExternalSort", (ISortAlg) new ExternalSort());
        sortAlgs.put("ConcurrentExternalSort", (ISortAlg) new ConcurrentExternalSort());
        sortAlgs.put("MapReduceSort", (ISortAlg) new MapReduceSort());
    }

    public static ISortAlg getSortAlg(String type) {
        if (type == null || type.isEmpty()) {
            throw new IllegalArgumentException("type should not be empty");
        }
        return sortAlgs.get(type);
    }
}
策略使用



public class Sorter {
    private static final long GB = 1000 * 1000 * 1000;
    private static final List<AlgRange> algs = new ArrayList<>();

    static {
        algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
        algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
        algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
        algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
    }

    public void sortFile(String filePath) {
        // 省略校验逻辑
        File file = new File(filePath);
        long fileSize = file.length();
        ISortAlg sortAlg = null;
        for (AlgRange algRange : algs) {
            if (algRange.inRange(fileSize)) {
                sortAlg = algRange.getAlg();
                break;
            }
        }

        sortAlg.sort(filePath);
    }

    private static class AlgRange {
        private long start;
        private long end;
        private ISortAlg alg;
        public AlgRange(long start, long end, ISortAlg alg) {
            this.start = start;
            this.end = end;
            this.alg = alg;
        }
        public ISortAlg getAlg() {
            return alg;
        }

        public boolean inRange(long size) {
            return size >= start && size < end;
        }
    }
}

代码参考: https://github.com/hero-joey/java-study-examples/tree/master/designpatten/src/com/hero/designpatten

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值