策略模式

Posted on 2021-05-26 13:42  FLGB  阅读(102)  评论(0编辑  收藏  举报

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。我们知道,工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,不过,它解耦的是策略的定义、创建、使用这三部分。

策略类的定义比较简单,包含一个策略接口和一组实现这个接口的策略类。因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略

public interface ISortAlg {
    void sort(String filePath);
}

定义策略实现类

package com.lf.pattern.strategy;

public class ConcurrentExternalSort implements ISortAlg{

    @Override
    public void sort(String filePath) {

    }
}
package com.lf.pattern.strategy;

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

    }
}
package com.lf.pattern.strategy;

public class QuickSort implements ISortAlg{

    @Override
    public void sort(String filePath) {

    }
}
package com.lf.pattern.strategy;

public class MapReduceSort implements ISortAlg{

    @Override
    public void sort(String filePath) {

    }
}

定义策略工厂类,从工厂里取对象

package com.lf.pattern.strategy;

import java.util.HashMap;
import java.util.Map;

/**
 * 策略工厂类
 */
public class SortAlgFactory {

    private static final Map<String, ISortAlg> algs = new HashMap<>();

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

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

策略的使用:

package com.lf.pattern.strategy;

import java.io.File;

public class IfSorter {

        private static final long GB = 1000 * 1000 * 1000;

        public void sortFile(String filePath) {
            // 省略校验逻辑
            File file = new File(filePath);
            long fileSize = file.length();
            ISortAlg sortAlg;
            //消除大量的if/else,让代码结构更优雅
            if (fileSize < 6 * GB) { // [0, 6GB)
                sortAlg = SortAlgFactory.getSortAlg("QuickSort");
            } else if (fileSize < 10 * GB) { // [6GB, 10GB)
                sortAlg = SortAlgFactory.getSortAlg("ExternalSort");
            } else if (fileSize < 100 * GB) { // [10GB, 100GB)
                sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort");
            } else { // [100GB, ~)
                sortAlg = SortAlgFactory.getSortAlg("MapReduceSort");
            }
            sortAlg.sort(filePath);
        }
}

消除大量if/else,代码优雅化、健壮化

package com.lf.pattern.strategy;


import java.io.File;
import java.util.ArrayList;
import java.util.List;

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;
        }
    }
}

如果不想改动代码,则可以做成注解或者配置,扫描注解或配置加载进list,然后查表法即可

Copyright © 2024 FLGB
Powered by .NET 9.0 on Kubernetes