书本定义
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
读完有什么感觉?反正我开始读了10遍后是这个样子:
后来我学会了对它进行解读,于是有了下面的版本:
策略模式定义了算法族(可以理解为很多行为的集和,即一系列行为),分别封装起来(意味着可以直接使用),让他们之间可以互相替换(就是字面上的意思,他们可以互相替换),此模式让算法的变化独立于使用算法的客户(啥意思?)。
怎么样,不出所料,仍然
这个时候,实例闪亮登场
萌仔新开发了一款游戏,在这个游戏中,我们可以new一个又一个鸭子,这个鸭子有两个属性(技能),第一个是叫声(呱呱叫、吱吱叫、哑巴不会叫等);第二个是飞行(正常地用翅膀飞、火箭动力支持飞、不会飞等)。在new一个鸭子后,我们可以为它的叫声和飞行方式赋予不同的值(期间还可以不断修改),从而触发出不同的叫声和飞行动作。
在上面的鸭子类的设计中,我们可以采用策略模式。
不过上面这个例子也太牵强了吧/笑哭
设计类图(一定要看到文章最后的总结!)
代码(一定要看到文章最后的总结!)
# 策略模式[strategy pattern]
## INSTRUCTION
## PROGRAM STRUCTURE
- template_class 包中是抽象类 定义了鸭子类的模板
- template_interface 包中是方法的接口 一个接口定义一种鸭子的行为 供其他类进行实现
- impled_interface_class 实现了template_interface的类 一个类就是鸭子的一种行为
- extended_class 继承了抽象类的类 是真正的、可以被实例化的鸭子类
public abstract class Duck 模板鸭子 用于其他鸭子类继承并个性化、特殊化
package com.headfirst.designpatterns.strategy.template_class;
import com.headfirst.designpatterns.strategy.template_interface.FlyBehavior;
import com.headfirst.designpatterns.strategy.template_interface.QuackBehavior;
/**
* 模板鸭子 用于其他鸭子类继承并特殊化
*/
public abstract class Duck {
/******************** 属性全部封装成private *********************/
private FlyBehavior flyBehavior;
private QuackBehavior quackBehavior;
/******************** 构造器 *********************/
public Duck() {
}
/******************** 涉及到属性的方法(一般不重写) *********************/
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
public void performFly() {
this.getFlyBehavior().fly();
}
public void performQuack() {
this.getQuackBehavior().quack();
}
public FlyBehavior getFlyBehavior() {
return flyBehavior;
}
public QuackBehavior getQuackBehavior() {
return quackBehavior;
}
/******************** 其他方法(可重写) *********************/
public abstract void display();
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
public interface FlyBehavior 鸭子的飞行方式接口
package com.headfirst.designpatterns.strategy.template_interface;
/**
* 飞行接口 用于具体的飞行类实现 具体化飞行的行为
* 一个类就是一种飞方式
*/
public interface FlyBehavior {
public void fly();
}
鸭子的叫声方式接口
package com.headfirst.designpatterns.strategy.template_interface;
/**
* 呱呱叫声接口 用于具体的呱呱叫声类实现 具体化呱呱叫的行为
* 一个类就是一种呱呱叫方式
*/
public interface QuackBehavior {
public void quack();
}
虚假的叫声类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.QuackBehavior;
/**
* FakeQuack 伪造的、佯装的呱呱叫
*/
public class FakeQuack implements QuackBehavior {
public void quack() {
System.out.println("Qwak");
}
}
呱呱叫声类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.QuackBehavior;
/**
* 一般的呱呱叫
*/
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
哑巴(不会叫)类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.QuackBehavior;
/**
* 哑鸭子(不会呱呱叫)
*/
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>");
}
}
吱吱叫声类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.QuackBehavior;
/**
* Squeak 吱吱叫
*/
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}
不会飞类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.FlyBehavior;
/**
* 不会飞
*/
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
火箭动力驱动飞行类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.FlyBehavior;
/**
* 火箭动力飞
*/
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
用翅膀飞类
package com.headfirst.designpatterns.strategy.impled_interface_class;
import com.headfirst.designpatterns.strategy.template_interface.FlyBehavior;
/**
* 用翅膀飞
*/
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
诱饵鸭 不会飞 也不会叫
package com.headfirst.designpatterns.strategy.extended_class;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyNoWay;
import com.headfirst.designpatterns.strategy.impled_interface_class.MuteQuack;
import com.headfirst.designpatterns.strategy.template_class.Duck;
/**
* 诱饵鸭 不会飞 也不会叫
*/
public class DecoyDuck extends Duck {
public DecoyDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new MuteQuack());
}
public void display() {
System.out.println("I'm a duck Decoy");
}
}
野鸭 正常一般的呱呱叫 用翅膀飞
package com.headfirst.designpatterns.strategy.extended_class;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyWithWings;
import com.headfirst.designpatterns.strategy.impled_interface_class.Quack;
import com.headfirst.designpatterns.strategy.template_class.Duck;
/**
* 野鸭 正常一般的呱呱叫 用翅膀飞
*/
public class MallardDuck extends Duck {
public MallardDuck() {
setQuackBehavior(new Quack());
setFlyBehavior(new FlyWithWings());
}
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
模型鸭 不会飞 一般的呱呱叫
package com.headfirst.designpatterns.strategy.extended_class;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyNoWay;
import com.headfirst.designpatterns.strategy.impled_interface_class.Quack;
import com.headfirst.designpatterns.strategy.template_class.Duck;
/**
* 模型鸭 不会飞 一般的呱呱叫
*/
public class ModelDuck extends Duck {
public ModelDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new Quack());
}
public void display() {
System.out.println("I'm a model duck");
}
}
红头鸭 不会飞 一般的呱呱叫
package com.headfirst.designpatterns.strategy.extended_class;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyNoWay;
import com.headfirst.designpatterns.strategy.impled_interface_class.Quack;
import com.headfirst.designpatterns.strategy.template_class.Duck;
/**
* 红头鸭 不会飞 一般的呱呱叫
*/
public class RedHeadDuck extends Duck {
public RedHeadDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new Quack());
}
public void display() {
System.out.println("I'm a real Red Headed duck");
}
}
橡皮鸭 不会飞 吱吱叫
package com.headfirst.designpatterns.strategy.extended_class;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyNoWay;
import com.headfirst.designpatterns.strategy.impled_interface_class.Squeak;
import com.headfirst.designpatterns.strategy.template_class.Duck;
/**
* 橡皮鸭 不会飞 吱吱叫
*/
public class RubberDuck extends Duck {
public RubberDuck() {
setFlyBehavior(new FlyNoWay());
setQuackBehavior(new Squeak());
}
public void display() {
System.out.println("I'm a rubber duckie");
}
}
模式验证和测试
package com.headfirst.designpatterns.strategy;
import com.headfirst.designpatterns.strategy.extended_class.DecoyDuck;
import com.headfirst.designpatterns.strategy.extended_class.MallardDuck;
import com.headfirst.designpatterns.strategy.extended_class.ModelDuck;
import com.headfirst.designpatterns.strategy.extended_class.RubberDuck;
import com.headfirst.designpatterns.strategy.impled_interface_class.FlyRocketPowered;
import com.headfirst.designpatterns.strategy.template_class.Duck;
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck(); // 创建一个野鸭
RubberDuck rubberDuckie = new RubberDuck(); // 创建一个橡皮鸭
DecoyDuck decoy = new DecoyDuck(); // 创建一个诱饵鸭
Duck model = new ModelDuck(); // 用父类引用创建一个模型鸭
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
model.performFly();
/**
* 【动态设置鸭子的飞行方式 也可以设置叫声】
* 这里便是策略设计模式的根本体现!!!
* (1)鸭子的各种叫声是一族算法(一系列叫声类)
* (2)鸭子的各种飞行方式也是一族算法(一系列飞行方式类)
* 这与定义是吻合的,同一算法族中的各个类是可以在代码运行期间相互替换的!!!
* 所谓的策略,就是同一个鸭子,我们可以动态的为它选择不同的叫声和飞行方式
* 这个选择的过程,就是策略的动作体现!
*/
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
/* 【运行结果】
Quack
Squeak
<< Silence >>
I can't fly
I'm flying with a rocket
*/
}
}
回顾定义 并总结
策略模式定义了算法族(可以理解为很多行为的集和,即一系列行为),分别封装起来(意味着可以直接使用),让他们之间可以互相替换(就是字面上的意思,他们可以互相替换),此模式让算法的变化独立于使用算法的客户(啥意思?这个地方我目前理解为程序员对算法族,也就是鸭子的各种叫声类和飞行类的调用、互相替换等)
model.performFly();
/**
* 【动态设置鸭子的飞行方式 也可以设置叫声】
* 这里便是策略设计模式的根本体现!!!
* (1)鸭子的各种叫声是一族算法(一系列叫声类)
* (2)鸭子的各种飞行方式也是一族算法(一系列飞行方式类)
* 这与定义是吻合的,同一算法族中的各个类是可以在代码运行期间相互替换的!!!
* 所谓的策略,就是同一个鸭子,我们可以动态的为它选择不同的叫声和飞行方式
* 这个选择的过程,就是策略的动作体现!
*/
model.setFlyBehavior(new FlyRocketPowered()); // 替换(改变)鸭子的飞行模式(方式)
model.performFly();
(对于策略模式的理解有待更新...)
谢谢读取 ~ >.<