给对象排序的例子
一个普通的冒泡排序,现在我想让它对某一对象进行排序,那我们就会具体来实现通过对象的什么属性来决定大小。
public static void sort(Object[] a) {
Cat[] c = (Cat[])a;
for (int i = a.length; i > 0; i--) {
for (int j = 0; j < i - 1; j++) {
if (c[j].getHeight() > c[j+1].getHeight()) {
swap(c,j,j+1);
}
}
}
}
可是当我现在又想为另外一个对象进行排序,例如为狗的weight排序,难道单独为一个对象重写sort方法吗??如果有N个,那岂不是要实现N次,现在我们希望这个排序算法可以多次复用,不用更改。
这个时候我们就用上接口,由比较的对象来决定比较的方法
public interface Comparable {
int compareTo(Object o);
}
Cat实现Comparable接口里的compareTo方法
@Override
public int compareTo(Object o) {
if (o instanceof Cat) {
Cat c = (Cat) o;
if (this.getHeight() > c.getHeight()) {
return 1;
} else if (this.getHeight() < c.getHeight()) {
return -1;
} else return 0;
}
return -100;
}
排序方法的改变
public static void sort(Object[] a) {
for (int i = a.length; i > 0; i--) {
for (int j = 0; j < i - 1; j++) {
Comparable o1 = (Comparable) a[j];
Comparable o2 = (Comparable) a[j+1];
if (o1.compareTo(o2) == 1) {
swap(a,j,j+1);
}
}
}
}
可是现在我们比较的方式已经定死,compareTo只有一个方法,比如是比较Cat的height的大小。我们现在需要灵活的指定排序的方法,必定牵扯到多态
需要一个新的接口,大小比较器
Comparator
public interface Comparator {
int compare(Object o1,Object o2);
}
猫的比较方法实现Comparator 接口的compare
public class CatHeightComparator implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Cat c1 = (Cat)o1;
Cat c2 = (Cat)o2;
if(c1.getHeight() > c2.getHeight()) return 1;
else if(c1.getHeight() < c2.getHeight()) return -1;
return 0;
}
}
修改Cat里的方法
@Override
public int compareTo(Object o) {
return comparator.compare(this, o); //在Comparable接口里的这个方法,作比较的是comparator接口里的compare具体方法
}
为什么要用策略模式
将来的某一天,也许你的代码需要更新,来支持新的业务场景,如果将要更改的那部分代码的修改影响到了那些基本不用动的代码,耦合度之高,产生的结果:工作量大,容易出错。
软件工程的思想就是抽离封装那些经常要改变的,与那些不动的隔离开。
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法与使用算法之间的耦合。
比如jdk里的comparable接口和comparator接口,comparable接口确定可以比较的对象,comparator接口则是比较的算法策略
策略模式 基本
//Strategy类,定义所有支持的算法的公共接口
public interface Strategy
{
public void algorithmInterface();
}
//ConcreteStrategy封装了具体的算法或行为,继承于Strategy
public class ConcreteStrategyA implements Strategy
{
public void algorithmInterface()
{
System.out.println("算法A实现");
}
}
public class ConcreteStrategyB implements Strategy
{
public void algorithmInterface()
{
System.out.println("算法B实现");
}
}
public class ConcreteStrategyC implements Strategy
{
public void algorithmInterface()
{
System.out.println("算法C实现");
}
}
//Context用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用
public class Context
{
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public void contextInterface()
{
strategy.algorithmInterface();
}
}
//客户端代码
public class Main
{
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();
}
}
策略模式的应用场景
- 需要相关的类仅仅是行为差异
- 运行时选取不同的算法变体
- 通过条件语句在多个分支中选取一
缺点
- 是通过新增对象来实现算法家族,时间久了就很多
- 客户代码需要注入策略来实现