设计模式-Strategy策略模式详解

策略模式是什么?

策略模式定义一系列算法,封装每个算法,并使他们可以互换,不同的策略可以让算法独立于使用它们的客户而变化。 以上定义来自设计模式之美

是不是很抽象,下面我们就用模拟Comparator接口为大家讲解策略模式,首先我定义一个Cat类,里面有weight,height,age 属性


public class Cat {
    
    
    int weight, height,age;

    public Cat(int weight, int height,int age) {
    
    
        this.weight = weight;
        this.height = height;
        this.age = age;
    }

    @Override
    public int compareTo(Cat c) {
    
    

        if(this.weight < c.weight) {
    
    
            return -1;
        } else if(this.weight > c.weight) {
    
    
            return 1;
        } else {
    
    
            return 0;
        }
    }


    @Override
    public String toString() {
    
    
        return "Cat{" +
            "weight=" + weight +
            ", height=" + height +
            ", age=" + age +
            '}';
    }

}

现在我们要实现Cat类数组的排序,按weight属性升序,我们定义一个Sorter类,Cat类中定义compareTo方法,方法是按Cat类中的weight属性比较,我们通过选择排序实现Cat数组的排序

public class Sorter {
    
    

    public void sort(Cat[] arr) {
    
    
        //选择排序
        for(int i=0; i<arr.length - 1; i++) {
    
    
            int minPos = i;

            for(int j=i+1; j<arr.length; j++) {
    
    
                minPos = arr[j].compareTo(arr[minPos])==-1 ? j : minPos;
            }
            swap(arr, i, minPos);
        }
    }

    void swap(Cat[] arr, int i, int j) {
    
    
        Cat temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
     public static void main(String[] args) {
    
    
        Cat[] a = {
    
    new Cat(3, 3), new Cat(5, 5), new Cat(1, 1)};
        Sorter sorter = new Sorter();
        sorter.sort(a);
        System.out.println(Arrays.toString(a));
      
    }
}

假如现在我们要实现Cat类heigt属性或age属性排序,我们是不是每次都要修改compareTo方法,在设计模式中,有个对修改关闭,对扩展开放的开闭原则,我们每次都去修改compareTo方法违背了设计模式的思想,我们怎么进行扩展,我们定义Comparator接口,我们要实现那个属性的排序,就定义哪个属性的比较器

public interface Comparator<T> {
    
    
    int compare(T o1, T o2);
}

height升序属性的比较器

public class CatHeightComparator implements Comparator<Cat> {
    
    
    @Override
    public int compare(Cat o1, Cat o2) {
    
    
        if(o1.height > o2.height) {
    
    
            return 1;
        } else if (o1.height < o2.height) {
    
    
            return -1;
        } else {
    
    
            return 0;
        }
    }
}
public void sort(T[] arr, Comparator<T> comparator) {
    
    
    for(int i=0; i<arr.length - 1; i++) {
    
    
        int minPos = i;
        for(int j=i+1; j<arr.length; j++) {
    
    
            minPos = comparator.compare(arr[j],arr[minPos])==-1 ? j : minPos;
        }
        swap(arr, i, minPos);
    }
}

void swap(T[] arr, int i, int j) {
    
    
    T temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}


public static void main(String[] args) {
    
    
  
    Cat[] a = {
    
    new Cat(3, 3, 3), new Cat(5, 5, 5), new Cat(1, 1, 1)};
  
    Sorter<Cat> sorter = new Sorter<>();
    
    sorter.sort(a,new CatHeightComparator());
    System.out.println(Arrays.toString(a));
}


以此类推,我们要实现age属性的排序,我义Cat类age的比较器,要实现weight属性的排序,就实现Cat类weight比较器,以上就是Comparator接口实现策略模式的过程,我们可以提前的把这些比较器定义成枚举类,在程序初始化的时候将每个比较器放入常量map当中,想要那种比较器就从map中取,避免if…else…判断,增加一个策略,就在初始化了添加一个

public enum ComparatorEnum {
    
    
    AGE("age","age排序"),
    WEIGHT("weight","weight排序"),
    HEIGHT("height","height排序");
    
    private String code;
    
    private String desc;

    ComparatorEnum(String code, String desc) {
    
    
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
    
    
        return code;
    }

    public String getDesc() {
    
    
        return desc;
    }
}
	private static final Map<String, Comparator> comparatorMap= new HashMap<>(); 
	static {
    
     
    	shareStrategies.put("height", new CatHeightComparator()); 
    	...
   		...
   
	}

策略模式优缺点

  • 优点
  1. 算法策略可以自由切换
  2. 避免使用多重条件转移语句,如if…else…语句、switch 语句
  3. 策略模式符合开闭原则
  • 缺点
  1. 必须知道所有的策略,并且自行决定使用哪一个策略类。
  2. 代码中会产生非常多策略类,增加维护难度。

猜你喜欢

转载自blog.csdn.net/ahuangqingfeng/article/details/124371887
今日推荐