首先澄清策略模式概念:
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客
户。
HeadFirst设计模式中基于SimUDuck游戏介绍使用策略模式实现鸭子的飞行与叫声两个行为。通过为鸭子实现飞行方法进入主题,有的鸭子会飞,有的鸭子不会飞,具体的鸭子实现是通过继承自Duck基类实现,在基类中定义了鸭子飞行的行为,若子类鸭子中没有飞行行为,比如橡皮鸭,则需要再次实现飞行方法以覆盖父类中定义过得行为。又或者不同子类的鸭子飞行的方式不一样,则也需要单独在子类中重新覆盖父类的方法。而且,若日后鸭子的飞行行为发生了变化,则还需要在子类中逐个修改飞行方法,况且还不能再执行过程中动态改变鸭子的飞行行为。这样的实现非常不具有弹性,况且日后维护起来也比较麻烦。
为了消化策略模式,本文基于TypeScript演示策略模式的应用。
执行 tsc strategyModel.ts 生成对应的js文件;
执行 node strategyModel.js运行
abstract class FlyBehavior {
constructor() {}
abstract fly(): void;
}
class FlyHigher extends FlyBehavior {
constructor() {
super();
}
fly() {
console.log('flying up ground 100 meter');
}
}
class NoFly extends FlyBehavior {
constructor() {
super();
}
fly() {
console.log('I can not flying');
}
}
class FlyLow extends FlyBehavior {
constructor() {
super();
}
fly() {
console.log("flying up ground 10 meter");
}
}
abstract class SnarlBehavior {
constructor() {}
abstract snarl();
}
class BirdSnarl extends SnarlBehavior {
constructor() {
super();
}
snarl() {
console.log('jiji');
}
}
class DogSnarl extends SnarlBehavior {
constructor() {
super();
}
snarl() {
console.log('wang wang');
}
}
abstract class Animal {
snarlBehavior: SnarlBehavior;
flyBehavior: FlyBehavior;
constructor () {}
abstract display();
makeSound() {
this.snarlBehavior.snarl();
}
fly() {
this.flyBehavior.fly();
}
}
class Dog extends Animal {
constructor() {
super();
this.flyBehavior = new NoFly();
this.snarlBehavior = new DogSnarl();
}
display() {
console.log('black dog');
}
setFlyBehavior(newFlyBehavior: FlyBehavior) {
this.flyBehavior = newFlyBehavior;
}
}
class Eagle extends Animal {
constructor() {
super();
this.flyBehavior = new FlyHigher();
this.snarlBehavior = new BirdSnarl();
}
display() {
console.log('white eagle');
}
}
let dog: Dog = new Dog();
dog.fly(); // I can not flying
dog.makeSound(); // wang wang
let flyLow = new FlyLow();
dog.setFlyBehavior(flyLow); // 动态改变dog的飞行行为,使其可以飞行
dog.fly(); // flying up ground 10 meter
let eagle: Eagle = new Eagle();
eagle.fly(); // flying up ground 100 meter
eagle.makeSound(); // jiji
若是想修改某一类飞行方法,则直接在相应的飞行子类中修改即可。策略模式中用到了类的多态性质,即定义了一个基类型的变量,在运行时才对其赋值,将具体的子类对象赋值给该变量。
常用设计准则:
1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不变的代码混在一起。
2. 针对接口编程,而不是针对具体实现编程。
3. 多用组合,少用继承。
关于抽象类与抽象方法:
本例中,声明了FlyBehavior抽象类,定义了fly抽象方法,注意抽象方法只能定义在抽象类中。抽象类不能实例化对象,抽象类中定义的抽象方法必须在子类中实现。