23种设计模式之策略模式(20)

  • 面向对象编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。

  • 策略模式(Strategy):他定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

  • 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

  • 策略模式的Strangy类层次为context定义了一系列可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。

  • 策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

  • 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个独立的stratege类中,可以在使用这些行为的类中消除条件语句。

  • 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

  • 在基本的策略模式中选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。

  • 任何需求的变更都是需要成本的。

  • 对同一件事的不同处理方式,本章是的这一件事指的是排序,对数组,对猫,对狗,对猫的体重,对猫的身高进行排序。

  • 在需求一步一步被提出的时候,代码的可扩展性如何做到最好。
    在这里插入图片描述

  • Context.java

    public class Context {
        Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        //上下文接口
        public void ContextInterface() {
            strategy.AlgorithmInterface();
        }
    }
    
  • Strategy.java

    public abstract class Strategy {
        //算法方法
        public abstract void AlgorithmInterface();
    }
    
  • ConcreteStrategyA.java

    public class ConcreteStrategyA extends Strategy {
        @Override public void AlgorithmInterface() {
            System.out.println("换成绿皮皮");
        }
    }
    
  • ConcreteStrategyB.java

    public class ConcreteStrategyB extends Strategy {
        @Override public void AlgorithmInterface() {
            System.out.println("换成黄皮皮");
        }
    }
    
  • ConcreteStrategyC.java

    public class ConcreteStrategyC extends Strategy {
        @Override public void AlgorithmInterface() {
            System.out.println("换成蓝皮皮");
        }
    }
    
  • StrategyMain .java

    public class StrategyMain {
        public static void main(String[] args) {
            Context context;
    
            context = new Context(new ConcreteStrategyA());
            context.ContextInterface();
    
            context = new Context(new ConcreteStrategyB());
            context.ContextInterface();
    
            context = new Context(new ConcreteStrategyC());
            context.ContextInterface();
        }
    }
    
1在最开始有一个对数组进行排序的需求。。
  • Main.java

    public class Main {
    
    	public static void main(String[] args) {
    		int[] a = {9,2,3,5,7,1,4};
    		Sorter sorter = new Sorter();
    		sorter.sort(a);
    		System.out.println(Arrays.toString(a));
    	}
    }
    
  • Sort.java

    public class Sorter {
    
    	public static void sort(int[] arr) {
    		for(int i=0;i<arr.length;i++) {
    			int minPos = i;
    			for (int j = i+1; j < arr.length; j++) {
    				minPos = arr[j]<arr[minPos]  ? j :minPos;
    			}
    			swap(arr,i,minPos);
    		}
    	}
    	
    	static void swap(int[] arr, int i, int j) {
    		int temp = arr[i];
    		arr[i]= arr[j];
    		arr[j]= temp; 
    	}
    }
    
2后来需要对猫(体重)进行排序
  • Main.java

    public class Main {
    
    	public static void main(String[] args) {
    //		int[] a = {9,2,3,5,7,1,4};
    		Cat[] cats = {new Cat(5, 5), new Cat(3, 3), new Cat(7, 7)};
    		Sorter sorter = new Sorter();
    		sorter.sort(cats);
    		System.out.println(Arrays.toString(cats));
    	}
    }
    
  • Sort.java

    public class Sorter {
    
    	public static void sort(Cat[] arr) {
    		for(int i=0;i<arr.length;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);
    		}
    	}
    	
    	static void swap(Cat[] arr, int i, int j) {
    		Cat temp = arr[i];
    		arr[i]= arr[j];
    		arr[j]= temp; 
    	}
    }
    
  • Cat.java

    public class Cat {
    	int weight,height;
    
    	public Cat(int weight, int height) {
    		super();
    		this.weight = weight;
    		this.height = height;
    	}
    	
    	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 + "]";
    	}
    }
    
3再后来需要对狗进行排序
  • Main.java

    public class Main {
    public static void main(String[] args) {
    //Cat[] cats = {new Cat(5, 5), new Cat(3, 3), new Cat(7, 7)};
    	Dog[] dogs = {new Dog(3),new Dog(5),new Dog(1)};
    	Sorter sorter = new Sorter();
    	sorter.sort(dogs);
    	System.out.println(Arrays.toString(cats));
    }
    
  • Cat.java

    public class Cat implements Compareble{
    	int weight,height;
    
    	public Cat(int weight, int height) {
    		super();
    		this.weight = weight;
    		this.height = height;
    	}
    	
    	public int compareTo(Object o) {
    		Cat c = (Cat)o; 
    		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 + "]";
    	}
    }
    
  • Dog.java

    public class Dog implements Compareble{
    	int food;
    
    	public Dog(int food) {
    		super();
    		this.food = food;
    	}
    
    	@Override
    	public int compareTo(Object o) {
    		Dog dog = (Dog)o;
    		if(this.food < dog.food) return -1;
    		else if(this.food > dog.food) return 1;
    		else return 0;
    	}
    
    	@Override
    	public String toString() {
    		return "Dog [food=" + food + "]";
    	};
    }
    
  • Sorter.java

    public class Sorter {
    
    	public static void sort(Comparable[] arr) {
    		for(int i=0;i<arr.length;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);
    		}
    	}
    	
    	static void swap(Comparable[] arr, int i, int j) {
    		Comparable temp = arr[i];
    		arr[i]= arr[j];
    		arr[j]= temp; 
    	}
    }
    
  • Comparable.java

    public interface Comparable<T> {
    	public int compareTo(T o);
    }
    
4再再后来需要对猫的身高进行排序
  • 把比较器单独作为一个类使用,这样修改比较方式的时候就不用更改源代码,仅需增加一个方法即可

  • Main,java

    public class Main {
    	public static void main(String[] args) {
    		Dog[] dogs = {new Dog(3),new Dog(5),new Dog(1)};
    		Sorter sorter = new Sorter();
    		sorter.sort(dogs,new DogComparator());
    		System.out.println(Arrays.toString(dogs));
    		
    		Cat[] cats = {new Cat(5, 2), new Cat(3, 5), new Cat(7, 1)};
    		Sorter<Cat> sorter2 = new Sorter<Cat>();
    		Sorter.sort(cats,new CatWeightComparator());
    		System.out.println("使用CatWeightComparator比较器对猫进行排序:");
    		System.out.println(Arrays.toString(cats));
    		
    		Sorter.sort(cats,new CatHeightComparator());
    		System.out.println("使用CatHeightComparator比较器对猫进行排序:");
    		System.out.println(Arrays.toString(cats));
    		
    		
    		Sorter.sort(cats,(c1,c2) -> {
    			if(c1.weight < c2.weight) return -1;
    			else if(c1.weight > c2.weight) return 1;
    			else return 0;
    		});
    		//这里使用lambad表达式仅是对lambda表达式的练习,这样写对策略模式并不匹配
    		System.out.println("使用Lambad表达式对猫(体重)进行排序:");
    		System.out.println(Arrays.toString(cats));
    	}
    }
    
  • Cat.java

    public class Cat{
    	int weight,height;
    
    	public Cat(int weight, int height) {
    		super();
    		this.weight = weight;
    		this.height = height;
    	}
    
    	@Override
    	public String toString() {
    		return "Cat [weight=" + weight + ", height=" + height + "]";
    	}
    }
    
  • Dog.java

    public class Dog {
    	int food;
    
    	public Dog(int food) {
    		super();
    		this.food = food;
    	}
    
    	@Override
    	public String toString() {
    		return "Dog [food=" + food + "]";
    	};
    }
    
  • Sorter.java

    public class Sorter<T> {
    
    	public static<T> void sort(T[] arr,Comparator<T> comparator) {
    		for(int i=0;i<arr.length;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);
    		}
    	}
    	
    	static<T> void swap(T[] arr, int i, int j) {
    		T temp = arr[i];
    		arr[i]= arr[j];
    		arr[j]= temp; 
    	}
    }
    
  • comparator.java

    @FunctionalInterface
    // 函数式接口仅有一个抽象方法,但可有多个default方法
    public interface Comparator<T> {
    	int compare​(T o1,T o2);
    	
    	//这个方法与代码内容无关
    	default void m() {
    		System.out.println("m");
    	}
    }
    
  • DogComparator.java

    public class DogComparator implements Comparator<Dog> {
    	public int compare​(Dog d1,Dog d2) {
    		if(d1.food < d2.food) return -1;
    		else if(d1.food > d2.food) return 1;
    		else return 0;
    	}
    }
    
  • CatWeightComparator.java

    public class CatWeightComparator implements Comparator<Cat> {
    	public int compare​(Cat c1,Cat c2) {
    		if(c1.weight < c2.weight) return -1;
    		else if(c1.weight > c2.weight) return 1;
    		else return 0;
    	}
    }
    
  • CatHeightComparator.java

    public class CatHeightComparator implements Comparator<Cat> {
    	public int compare​(Cat c1,Cat c2) {
    		if(c1.height < c2.height) return -1;
    		else if(c1.height > c2.height) return 1;
    		else return 0;
    	}
    }
    

    在这里插入图片描述

在这里插入图片描述

  • 为什么要有这个(默认方法)特性?

    首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

  • singleton - spring的bean工厂

  • https://docs.oracle.com/en/java/javase/14/docs/api/index.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值