鸭子问题
- 现有各个种类的鸭子,如野鸭、北京鸭、水鸭等;鸭子有各种行为,如叫、飞行等
- 需要显示鸭子的信息
传统方案解决鸭子问题
问题分析
- 所有鸭子都继承了Duck类,Duck类对某些行为的定义不一定满足所有鸭子
- 对超类的局部改动,就会影响所有子类
- 对于玩具鸭这样与其他鸭子行为大不相同的,需要重写父类的所有方法
策略模式
基本介绍
- 策略模式定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的用户
- 体现了设计原则:第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类;第三、多用聚合少用继承
原理
- Context:客户对象,持有成员变量strategy或其他行为策略,至于用到哪些策略,可以在构造器来指定
- Strategy:具体的策略行为的抽象
- ConcreteStrategy:对策略抽象的多态实现
策略模式解决鸭子问题
/***
* @author shaofan
* @Description 策略模式解决鸭子问题
*/
public class DuckInfo {
public static void main(String[] args) {
Duck wildDuck =new WildDuck();
Duck toyDuck = new ToyDuck();
wildDuck.fly();
toyDuck.fly();
}
}
abstract class Duck{
Flyable flyable;
public Duck(Flyable flyable){
this.flyable = flyable;
}
public void fly(){
flyable.fly();
}
}
class WildDuck extends Duck{
public WildDuck() {
super(new GoodFlyable());
}
}
class ToyDuck extends Duck{
public ToyDuck() {
super(new NoFlyable());
}
}
interface Flyable{
void fly();
}
class NoFlyable implements Flyable{
@Override
public void fly() {
System.out.println("不能飞");
}
}
class GoodFlyable implements Flyable{
@Override
public void fly() {
System.out.println("擅长飞");
}
}
class BadFlyable implements Flyable{
@Override
public void fly() {
System.out.println("不擅长飞");
}
}
源码分析
如Arrays中的sort方法,针对传入的Comparator,来确定排序的策略,如果没有传入则为默认的升序,
Comparator就是策略对象,排序行为和Arrays分离开了
总结
- 策略模式的关键是项目中的变化部分和不变的部分
- 策略模式的核心思想是:多用组合/聚合,少用继承;用行为类组合,而不是行为的继承。更有弹性
- 体现了开闭原则,客户端增加行为不修改原有代码,只需要添加一种策略或行为即可,避免了多重的if-else
- 提供了可以替换继承关系的方法,用策略将行为单独提取出来,使用聚合代替继承