面向对象编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
策略模式(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(); } }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; } }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 + "]"; } }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); }把比较器单独作为一个类使用,这样修改比较方式的时候就不用更改源代码,仅需增加一个方法即可
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