likes
comments
collection
share

通俗易懂设计模式(状态模式)

作者站长头像
站长
· 阅读数 9

状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变其行为。这种模式可以使对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象的状态转换需要很多条件语句时的问题,通过将状态的判断逻辑封装到具体状态类中,可以使代码更加简洁、易于维护。

状态模式的主要角色有:

  1. 上下文(Context):维护一个具体状态的引用,用于定义状态的接口,并实现状态的切换。
  2. 状态(State):定义一个接口,用于封装具体状态的行为。
  3. 具体状态(ConcreteState):实现状态接口,并具体实现状态的行为。

优点

  1. 状态模式将状态的判断逻辑封装到具体状态类中,使得代码更加简洁、易于维护。
  2. 状态模式可以使对象在不同状态下有不同的行为,使得对象的行为更加灵活。
  3. 状态模式可以将状态转换的逻辑分散到具体状态类中,使得状态转换更加灵活。

缺点

  1. 状态模式会增加系统的类的数量,可能导致系统更加复杂。
  2. 状态模式的实现可能会增加系统的开销,因为需要创建具体状态类的实例。

示例

以下是一个使用状态模式实现的简单示例:

// 状态接口
interface State {
    void handle(Context context);
}

// 具体状态A
class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("处理状态A");
        context.setState(new ConcreteStateB());
    }
}

// 具体状态B
class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("处理状态B");
        context.setState(new ConcreteStateA());
    }
}

// 上下文类
class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void handle() {
        state.handle(this);
    }
}

// 测试类
public class StatePatternDemo {
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());
        context.handle(); // 输出:处理状态A
        context.handle(); // 输出:处理状态B
        context.handle(); // 输出:处理状态A
    }
}

在这个示例中,我们定义了一个状态接口State,以及两个具体状态类ConcreteStateAConcreteStateBContext类维护一个具体状态的引用,并实现了状态的切换。在main方法中,我们创建了一个Context对象,并调用其handle方法来切换状态。

使用场景

场景一:在线购物网站的购物车状态管理

在在线购物网站中,购物车的状态可能包括“未支付”、“已支付”、“已发货”和“已完成”等。不同的状态下,购物车可以执行的操作是不同的。例如,在“未支付”状态下,用户可以添加商品、删除商品或修改商品数量;而在“已支付”状态下,用户只能查看订单详情。

使用状态模式来实现购物车的状态管理,可以让代码更加简洁、易于维护。具体实现如下:

// 状态接口
interface ShoppingCartState {
    void addProduct(ShoppingCart cart, Product product);
    void removeProduct(ShoppingCart cart, Product product);
    void modifyProductQuantity(ShoppingCart cart, Product product, int quantity);
    void pay(ShoppingCart cart);
    void ship(ShoppingCart cart);
}

// 未支付状态
class UnpaidState implements ShoppingCartState {
    @Override
    public void addProduct(ShoppingCart cart, Product product) {
        // 添加商品逻辑
    }

    @Override
    public void removeProduct(ShoppingCart cart, Product product) {
        // 删除商品逻辑
    }

    @Override
    public void modifyProductQuantity(ShoppingCart cart, Product product, int quantity) {
        // 修改商品数量逻辑
    }

    @Override
    public void pay(ShoppingCart cart) {
        // 支付逻辑
        cart.setState(new PaidState());
    }

    @Override
    public void ship(ShoppingCart cart) {
        // 禁止发货逻辑
    }
}

// 已支付状态
class PaidState implements ShoppingCartState {
    @Override
    public void addProduct(ShoppingCart cart, Product product) {
        // 禁止添加商品逻辑
    }

    @Override
    public void removeProduct(ShoppingCart cart, Product product) {
        // 禁止删除商品逻辑
    }

    @Override
    public void modifyProductQuantity(ShoppingCart cart, Product product, int quantity) {
        // 禁止修改商品数量逻辑
    }

    @Override
    public void pay(ShoppingCart cart) {
        // 禁止重复支付逻辑
    }

    @Override
    public void ship(ShoppingCart cart) {
        // 发货逻辑
        cart.setState(new ShippedState());
    }
}

// 已发货状态
class ShippedState implements ShoppingCartState {
    @Override
    public void addProduct(ShoppingCart cart, Product product) {
        // 禁止添加商品逻辑
    }

    @Override
    public void removeProduct(ShoppingCart cart, Product product) {
        // 禁止删除商品逻辑
    }

    @Override
    public void modifyProductQuantity(ShoppingCart cart, Product product, int quantity) {
        // 禁止修改商品数量逻辑
    }

    @Override
    public void pay(ShoppingCart cart) {
        // 禁止重复支付逻辑
    }

    @Override
    public void ship(ShoppingCart cart) {
        // 禁止重复发货逻辑
    }
}

// 购物车类
class ShoppingCart {
    private ShoppingCartState state;

    public ShoppingCart(ShoppingCartState state) {
        this.state = state;
    }

    public void setState(ShoppingCartState state) {
        this.state = state;
    }

    public void addProduct(Product product) {
        state.addProduct(this, product);
    }

    public void removeProduct(Product product) {
        state.removeProduct(this, product);
    }

    public void modifyProductQuantity(Product product, int quantity) {
        state.modifyProductQuantity(this, product, quantity);
    }

    public void pay() {
        state.pay(this);
    }

    public void ship() {
        state.ship(this);
    }
}

场景二:游戏角色的攻击状态管理

在一个游戏中,角色可能有多种攻击状态,如“普通攻击状态”、“连击状态”和“暴击状态”。在不同的攻击状态下,角色可以执行的攻击操作是不同的。例如,在“普通攻击状态”下,角色只能进行普通的攻击;而在“连击状态”下,角色可以进行连续的攻击。

使用状态模式来实现游戏角色的攻击状态管理,可以让代码更加简洁、易于维护。具体实现如下:

// 状态接口
interface AttackState {
    void attack(Character character);
}

// 普通攻击状态
class NormalAttackState implements AttackState {
    @Override
    public void attack(Character character) {
        // 普通攻击逻辑
    }
}

// 连击状态
class ComboAttackState implements AttackState {
    @Override
    public void attack(Character character) {
        // 连击攻击逻辑
    }
}

// 暴击状态
class CriticalAttackState implements AttackState {
    @Override
    public void attack(Character character) {
        // 暴击攻击逻辑
    }
}

// 角色类
class Character {
    private AttackState state;

    public Character(AttackState state) {
        this.state = state;
    }

    public void setState(AttackState state) {
        this.state = state;
    }

    public void attack() {
        state.attack(this);
    }
}

在这两个场景中,我们都使用了状态模式来管理对象的状态和行为。在第一个场景中,我们使用状态模式来管理购物车的状态和行为;在第二个场景中,我们使用状态模式来管理游戏角色的攻击状态和行为。通过使用状态模式,我们可以让代码更加简洁、易于维护,同时提高了代码的可扩展性和可重用性。