策略模式
Java设计模式之策略模式
前言:
最近在学习设计模式,看的书是《Head First 设计模式》首先介绍的就是策略模式(Strategy),我将结合书中描述的加上自己理解在此记录一下。
概念:
策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。我理解的是在处理某类业务时,将平等出现的情况封装起来,根据自己的需要去调用,这样也避免代码中出现大量的if-else,当然使用这些算法之前我们得了解每个算法的含义。
策略模式结构
策略模式涉及三个角色:
1、环境角色:持有一个Strategy的引用
2、抽象策略角色:通常是由一个接口或者抽象类实现。此角色给出所有的具体策略类所需的接口。
3、具体策略角色:包装了相关的算法和行为。
quackBehavior(叫行为)
代码
不同的鸭子有不一样的叫法(quack)(呱呱叫,吱吱叫,不会叫),不一样的飞行方法(fly)(翅膀飞,不会飞)
也就是Duck类内的fly()和quack()会随着鸭子的不同而改变,为了要把这两个行为从Duck类中分开,建立一组新类来代表每个行为。
首先有个鸭子类(Duck),飞行和叫这两个行为变量为接口类型,下面有这两个接口。所有的鸭子都会游泳(假设都会游泳,但你要硬是抬杠,旱鸭子不会游泳我就没办法了),游泳这个方法就不抽取了。
public abstract class Duck {
FlyBehavior flyBehavior;//飞行行为,接口类型
QuackBehavior quackBehavior;//叫行为,接口类型
public Duck(){
}
public void performQuack(){
quackBehavior.quack();
}
public void performFly(){
flyBehavior.fly();
}
public void swim(){
System.out.println("游泳");
}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
}
飞行行为接口及其实现类
public interface FlyBehavior {
void fly();
}
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("翅膀飞的鸭子");
}
}
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("不会飞");
}
}
public class FlyRocketPowered implements FlyBehavior {
@Override
public void fly() {
System.out.println("用火箭助推器飞");
}
}
叫行为接口及其实现类
public interface QuackBehavior {
void quack();
}
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("呱呱叫");
}
}
public class Squack implements QuackBehavior{
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
public class MuteQuack implements QuackBehavior{
@Override
public void quack() {
System.out.println("什么都不做,不会叫");
}
}
写到这里整个策略模式的架子就算搭建好了,Duck类有两个接口类型的行为变量,两个行为接口以及他们各自三个实现类,不同的鸭子怎么叫怎么飞 我们就直接调用就可以了。
测试
新建一个绿头鸭类 MallardDuck 继承Duck类,这是一只正常的鸭子会叫还会飞,既然是正常的那就new一个正常叫的行为和一个正常飞的行为。
public class MallardDuck extends Duck{
public MallardDuck(){
quackBehavior = new Quack();//正常的呱呱叫
flyBehavior = new FlyWithWings();//用翅膀飞
}
public void display(){
System.out.println("我是绿头鸭");
}
}
测试MallardDuck
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
mallard.performFly();
//调用performFly()方法会被委托给flyBehavior对象(也就是FlyWithWings实例),该对象是在绿头鸭构造器中设置的
mallard.performQuack();
//同上,叫的行为也是在绿头鸭的构造器中设置的。
}
}
结果
翅膀飞的鸭子
呱呱叫
注意
Duck类中有两个set方法,可以设定鸭子的行为,现在用个模型鸭(ModelDuck)举例子
public class ModelDuck extends Duck {
public ModelDuck(){
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display(){
System.out.println("我是模型鸭子");
}
}
public class MiniDuckSimulator {
public static void main(String[] args) {
ModelDuck model = new ModelDuck();
model.performFly();//现在不会飞
model.setFlyBehavior(new FlyRocketPowered());//把想用的飞行方法传进去,模型鸭就有这种飞行模式。
model.performFly();//加上火箭助推器飞行行为那不得起飞了啊。
}
}
运行结果
我是不会飞的鸭子
用火箭助推器飞
在运行时想要改变鸭子的行为,只需调用鸭子的setter方法就可以了。
总结
策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。