策略模式

策略模式

1
定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

设计过程的思考

1
当涉及“维护”时,为了“复用”目的而使用继承,解决并不完美。
1
不管当初软件设计得多好,一段时间之后,总是需要成长与改变,否则软件就会“死亡”。
1
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

设计原则

1
2
3
针对接口编程,而不是针对实现编程
针对接口编程真正的意思是针对超类型编程
抽象超类型可以是抽象类或者接口

首先将鸭子的飞定义成一个接口

1
2
3
public interface FlyBehavior {
public void fly();
}

然后定义叫的接口

1
2
3
public interface QuackBehavior {
public void quack();
}

定义鸭子的抽象父类, 将飞的接口和叫叫的接口当成鸭子的属性,同时增加两个set方法,以便能动态的设置飞和叫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
}
}

实现两个飞的接口的类

1
2
3
4
5
6
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!!");
}
}
1
2
3
4
5
6
public class FlyNoWay implements  FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly");
}
}

实现一个叫的接口的类

1
2
3
4
5
6
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}

实现一个具体的ModelDuck鸭子

1
2
3
4
5
6
7
8
9
10
11
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");
}
}

测试程序

1
2
3
4
5
6
7
8
9
10
11
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!!

笔记

  1. 关键将可变的抽离成接口,然后在父类中将接口定义成属性,增加可以改变属性的set方法。
  2. 同时实现自己行为的接口的类。(🌰中的飞和叫)
  3. 定义具体的子类,在构造方法中传入具体的行为的接口的类。
  4. 因为父类定义了可以改变属性接口的set方法,因为能变换具体的行为类。