设计模式笔记:策略模式

概念

策略模式定义了一些列算法,并把这些算法分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

组成

应用场景

优缺点

优点

缺点

应用举例

1. 策略类FlyBehavior及其两个实现类(FlyWithWings和FlyNoWay)

// 所有飞行行为都必须实现的接口。
public interface FlyBehavior{
    pulic void fly();
}
// 飞行行为的实现,给会飞的鸭子用
public class FlyWithWings implements FlyBehavior{
    public void fly(){
        System.out.println("I'm flying!");
    )
}
// 飞行行为的实现,给不会飞的鸭子用
public class FlyNoWay implements FlyBehavior{
    public void fly(){
        System.out.println("I can't fly!");
    )
}

2. 策略类QuackBehavior及其三个实现类(Quack、MuteQuack和Squeak)

public interface QuackBehavior{
    public void quack();
}
public class Quack implements QuackBehavior{
    public void quack(){
        System.out.println("Quack");
    }
}
public class MuteQuack implements QuackBehavior{
    public void quack(){
        System.out.println("Silence");
    }
}
public class Squeak implements QuackBehavior{
    public void quack(){
        System.out.println("Squeak");
    }
}

3. 上下文Duck类

public abstract class Duck

    // 每只鸭子都会引用实现的FlyBehavior对象
    FlyBehavior flyBehavior;

    // 每只鸭子都会引用实现的QuackBehavior对象
    QuackBehavior quackBehavior;
    
    public abstract void display();
    
    public void performFly(){
        // 鸭子对象不亲自处理fly行为,而是委托给flyBehavior引用的对象 
        flyBehavior.fly();
    }
    
    public void performQuack(){
        // 鸭子对象不亲自处理quack行为,而是委托给quackBehavior引用的对象 
        quackBehavior.quack();
    }
    
    public void swim(){
        System.out.println("All ducks float, even decoys!");
    }
 

4. 具体上下文实现MallardDuck类

public class MallardDuck extends Duck
    
    public MarllardDuck(){
        // 在构造函数中指定具体的策略
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }
    
    public void display(){
        System.out.println("I'm a real mallard duck!");
    }
 

5. 测试类MiniDuckSimulator

public class MiniDuckSimulator{
    public static void main(String[] args){
        Duck mallard = new MallardDuck();
        
        // 这会调用MallardQuack继承来的performQuack()方法
        // 进而委托给QuackBehavior对象处理
        mallard.performQuack();
        mallard.performFly();
    }
}

6. 运行代码

%java MiniDuckSimulator

Quack
I'm flying!

动态设定行为

1. 在Duck类中,加入两个新方法

public void setFlyBehavior(FlyBehavior fb){
    flyBehavior = fb;
}

public void setQuackBehavior(QuackBehavior qb){
    quackBehavior = qb;
}

2. 制造一个新的鸭子类型:模型鸭(ModelDuck)

public class ModelDuck extends Duck{
    public ModelDuck(){
        // 模型是不会飞的
        flyBehavior = new FlyNoWay();
        quackBehavior = new Quack();
    }
    
    public void display(){
        System.out.println("I'm a model duck");
    }
}

3. 建立一个新的FlyBehavior类型(FlyRockPowered)

public class FlyRockPowered implements FlyBehavior{
    // 一个新的飞行行为,用火箭飞行
    public void fly(){
        System.out.println("I'm flying with a rocket!");
    }
}

4. 改变测试类(MiniDuckSimulator),使用模型鸭,并使其用火箭飞行

public class MiniDuckSimulator{
    public static void main(String[] args){
        Duck model = new ModelDuck();
        // 第一次调用perform()会委托给flyBehavior对象,也就是FlyNoWay实例
        model.performFly();
        // 改变perform方法的flyBehavior对象,变成FlyRocketPowered实例
        model.setFlyBehavior(new FlyRocketPowered());
        // 第二次调用会委托给FlyRocketPowered实力
        model.perfomFly();        
    }
}

5. 运行代码

%java MiniDuckSimulator

Quack
I'm flying!
I can't fly!
I'm flying with a rocket!