介绍

策略模式uml类图

定义一套算法族,实现行为接口,对每一种行为进行封装。对象拥有某种行为接口,提供方法供外部动态替换行为。

优点

能够动态改变对象的行为,用户可以自己调用不同的行为、算法进行处理。增强了灵活性和可扩展性

缺点

每种算法需要定义相应的类

补充

可以与工厂模式配合使用,工厂模式用来创建具体的算法,避免多重条件判断

实现

  • 定义一个策略接口(行为,算法)
  • 定义不同实体类,实现策略接口
  • 定义Context类,包含策略属性(面向接口),并执行相应的方法
  • 外部通过创建具体的策略,传入Context中来实现动态替换对象(Context)的行为
//飞的行为接口
public interface FlyBehavior {
    void fly();
}
//具体的飞的行为
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("Fly With Wings");
    }
}
public class FlyNoWay implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("Fly no way");
    }
}

//叫的行为接口
public interface QuackBehavior {
    void quack();
}
//具体的叫的行为
public class Quack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Quack");
    }
}
public class Squeak implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Squeak");
    }
}
public class Mute implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("Mute");
    }
}
//Context对象,抽象鸭子,拥有飞和叫的行为
public abstract class Duck {
    private FlyBehavior flyBehavior=new FlyWithWings();
    private QuackBehavior quackBehavior=new Quack();

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    public abstract void display();
    public void fly(){
        flyBehavior.fly();
    }
    public void quack(){
        quackBehavior.quack();
    }
}
//具体的鸭子对象,对应具体的行为
//这部分是对策略模式的进一层封装,也可以由用户调用set方法动态更改Behavior
public class RedHeadDuck extends Duck {
    public RedHeadDuck() {
        setFlyBehavior(new FlyWithWings());
        setQuackBehavior(new Quack());
    }

    @Override
    public void display() {
        System.out.println("Red Head Duck");
    }
}
public class RubberDuck extends Duck {
    public RubberDuck() {
        setFlyBehavior(new FlyNoWay());
        setQuackBehavior(new Mute());
    }

    @Override
    public void display() {
        System.out.println("Rubber Duck");
    }
}
public class MallardDuck extends Duck {
    public MallardDuck() {
        setFlyBehavior(new FlyWithWings());
        setQuackBehavior(new Squeak());
    }

    @Override
    public void display() {
        System.out.println("Mallard Duck");
    }
}
//主程序
public class RunStrategy {
    public static void main(String[] args) {
        //对策略模式的封装,将具体的行为封装到具体的对象中
        Duck duck=new RedHeadDuck();
        duck.display();
        duck.fly();
        duck.quack();
        duck=new MallardDuck();
        duck.display();
        duck.fly();
        duck.quack();
        duck=new RubberDuck();
        duck.display();
        duck.fly();
        duck.quack();
        //动态修改行为
        duck.setQuackBehavior(new Squeak());
        duck.quack();
    }
}

状态模式

状态模式uml

//状态接口
public interface GameState {
    void clickNewGame();
    void clickHelpItem();
    void clickReturnMenu();
    void clickSettingsItem();
    void clickExit();
}
//主菜单状态
public class MenuState implements GameState {
    Game game;

    public MenuState(Game game) {
        this.game = game;
    }

    @Override
    public void clickNewGame() {
        System.out.println("Start a new game");
        game.setCurrentState(game.getRunState());
    }

    @Override
    public void clickHelpItem() {
        System.out.println("Click to help");
        game.setCurrentState(game.getHelpState());
    }

    @Override
    public void clickReturnMenu() {
        System.out.println("it is menu state");
    }

    @Override
    public void clickSettingsItem() {
        System.out.println("Click Setting");
        game.setCurrentState(game.getSettingState());
    }

    @Override
    public void clickExit() {
        System.out.println("Click to exit");
        game.setCurrentState(game.getExitState());
    }
}
//帮助状态,用户只能点击返回菜单,不能做其他行为
public class HelpState implements GameState{
    Game game;

    public HelpState(Game game) {
        this.game = game;
    }

    @Override
    public void clickNewGame() {
        System.out.println("it is help state");
    }

    @Override
    public void clickHelpItem() {
        System.out.println("it is help state");
    }

    @Override
    public void clickReturnMenu() {
        System.out.println("Return menu");
        game.setCurrentState(game.getMenuState());
    }

    @Override
    public void clickSettingsItem() {
        System.out.println("it is help state");
    }

    @Override
    public void clickExit() {
        System.out.println("it is help state");
    }
}
//设置状态
public class SettingState implements GameState{
    Game game;

    public SettingState(Game game) {
        this.game = game;
    }

    @Override
    public void clickNewGame() {
        System.out.println("it is setting state");
    }

    @Override
    public void clickHelpItem() {
        System.out.println("it is setting state");
    }

    @Override
    public void clickReturnMenu() {
        System.out.println("Return menu");
        game.setCurrentState(game.getMenuState());
    }

    @Override
    public void clickSettingsItem() {
        System.out.println("it is setting state");
    }

    @Override
    public void clickExit() {
        System.out.println("it is setting state");
    }
}
//运行状态
public class RunState implements GameState{
    Game game;

    public RunState(Game game) {
        this.game = game;
    }

    @Override
    public void clickNewGame() {
        System.out.println("it is game state");
    }

    @Override
    public void clickHelpItem() {
        System.out.println("it is game state");
    }

    @Override
    public void clickReturnMenu() {
        System.out.println("Return menu");
        game.setCurrentState(game.getMenuState());
    }

    @Override
    public void clickSettingsItem() {
        System.out.println("it is game state");
    }

    @Override
    public void clickExit() {
        System.out.println("it is game state");
    }
}
//Context对象拥有状态,且同一时间只由一种状态
public class Game {
    private GameState currentState=new MenuState(this);

    private GameState menuState=new MenuState(this);
    private GameState runState=new RunState(this);
    private GameState helpState=new HelpState(this);
    private GameState settingState=new SettingState(this);
    private GameState exitState=new ExitState(this);
    public void clickNewGame() {
        currentState.clickNewGame();
    }

    public void clickHelpItem() {
        currentState.clickHelpItem();
    }

    public void clickReturnMenu() {
        currentState.clickReturnMenu();
    }

    public void clickSettingsItem() {
        currentState.clickSettingsItem();
    }

    public void clickExit() {
        currentState.clickExit();
    }
    public String toString(){
        return "Game State: "+currentState.getClass().getSimpleName();
    }
    public GameState getMenuState() {
        return menuState;
    }

    public GameState getRunState() {
        return runState;
    }

    public GameState getHelpState() {
        return helpState;
    }

    public GameState getSettingState() {
        return settingState;
    }

    public GameState getExitState() {
        return exitState;
    }

    public GameState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(GameState currentState) {
        this.currentState = currentState;
    }
}
//主程序
public class Main {
    public static void main(String[] args) {
        Game game = new Game();
        System.out.println(game.toString());
        game.clickNewGame();
        game.clickHelpItem();
        game.clickReturnMenu();
        game.clickSettingsItem();
        game.clickReturnMenu();
        game.clickExit();
    }
}

策略模式和状态模式

uml类图相似,都能动态改变对象的行为。

状态模式的状态是自动切换的,由状态决定行为,用户无法改变逻辑,最多指定初始状态

策略模式是让用户指定更换的策略算法,动态替换算法

状态模式能够在对象内部改变行为,状态需要持有对象的引用(方法参数或者属性),通过调用对象setState,自动改变对象状态。

策略模式由用户在外部改变行为,策略不需要持有对象的引用。

通过状态模式和策略模式消除多重if……else:

策略模式将行为封装成策略,通过创建不同的策略并作为参数传给对象,代替条件判断,使用面向接口的方式,调用接口方法。

状态模式直接调用具体状态的方法,将条件行为移到状态中。

实例

Android动画的插值器和估值器

Glide中的缓存策略,可以自行实现DiskCache接口

results matching ""

    No results matching ""