介绍 :
- 在一个项目中存在大量相似的类 区别在于其具体实现 此时 可以使用策略模式来吧这些类封装为一个策略<或者说是算法> 以便进行灵活调用
- 优点 : 把程序中需要修改的代码单独分离 提高的程序扩展性
- 缺点 : 算法类会随着程序的扩展而越来越多 并且所有算法策略都需要对外暴露 以便调用对应算法
接下来使用一个例子来进行详细说明 :
- 我们现在有一些鸭子 他们会游泳 会叫 … … 接下来我们使用代码进行实现 如下图
- 如上这样定义超类实现基本属性 其他不同颜色鸭子进行继承实现是没有问题的 但是现在来了一个新的需求 我们需要让鸭子会飞 !!!
- 此时在超类添加一个会飞的属性 就可以了 但是我们发现所有的鸭子都会飞了 而我们不需要所有鸭子会飞 例如橡皮鸭是不会飞的 此时这样的架构就不满足需求了
- 接下来我们可以另外提供一个借口定义飞行属性 只让需要飞行的继承该接口 如下图
-
此时我们也可以实现以上需求 但是会出现新的问题
- 由于接口的具体实现是延迟到其具体实现类的 所以这样会造成大量重复的代码<在每一个会飞的鸭子类都需要定义一个飞行的属性>
-
我们的鸭子呢 也并不是全部都会叫 比如木头鸭既不会叫也不会飞 橡皮鸭会吱吱叫等等 此时使用上面的实现显然是无法满足的
-
那么我们有没有更好的解决方案呢 答案是肯定的 那就是策略模式 之前已经大概介绍过策略模式的基本概念 就是定义了一个个的算法 在代码运行时可以进行灵活添加创建
- 策略模式的类图如下 :
- 飞行类算法
public interface Call {
void call();
}
===========================
public class FlyImpl implements Fly {
@Override
public void fly() {
System.out.println("会飞的");
}
}
=========================
public class NotFlyImpl implements Fly {
@Override
public void fly() {
System.out.println("不会飞的");
}
}
- 叫声类算法
public interface Call {
void call();
}
=========================
public class SeQuackImpl implements Call {
@Override
public void call() {
System.out.println("吱吱叫");
}
}
========================
public class QuackImpl implements Call {
@Override
public void call() {
System.out.println("呱呱叫");
}
}
========================
public class NotImpl implements Call {
@Override
public void call() {
System.out.println("不会叫");
}
}
- 鸭子类
//鸭子类把算法接口作为属性
public class Duck {
private Fly fly;
private Call call;
//传入鸭子行为进行创建
public Duck(Fly fly, Call call) {
this.fly = fly;
this.call = call;
}
public void duck() {
fly.fly();
call.call();
}
}
- 测试
public class Test {
public static void main(String[] args) {
Duck duck = new Duck(new FlyImpl(),new QuackImpl());
duck.duck();
}
}