策略模式
定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
设计过程的思考
当涉及“维护”时,为了“复用”目的而使用继承,解决并不完美。
不管当初软件设计得多好,一段时间之后,总是需要成长与改变,否则软件就会“死亡”。
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
设计原则
针对接口编程,而不是针对实现编程
针对接口编程真正的意思是针对超类型编程
抽象超类型可以是抽象类或者接口
首先将鸭子的飞定义成一个接口
public interface FlyBehavior {
public void fly();
}
然后定义叫的接口
public interface QuackBehavior {
public void quack();
}
定义鸭子的抽象父类, 将飞的接口和叫叫的接口当成鸭子的属性,同时增加两个set方法,以便能动态的设置飞和叫
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
实现两个飞的接口的类
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!!");
}
}
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly");
}
}
实现一个叫的接口的类
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
实现一个具体的ModelDuck鸭子
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println(" I'm a model duck");
}
}
测试程序
public class HelloWorld {
public static void main(String[] args) {
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyWithWings());
model.performFly();
}
}
// I can't fly
// I'm flying!!
笔记
- 关键将可变的抽离成接口,然后在父类中将接口定义成属性,增加可以改变属性的set方法。
- 同时实现自己行为的接口的类。(🌰中的飞和叫)
- 定义具体的子类,在构造方法中传入具体的行为的接口的类。
- 因为父类定义了可以改变属性接口的set方法,因为能变换具体的行为类。