设计模式-状态模式

本文详细介绍了状态模式的概念、角色组成、使用环境、状态角色、具体状态角色及其实现方式,并通过银行账户状态管理的案例进行了分析。同时,对比了状态模式与策略模式的区别,阐述了它们在处理状态变化和算法变化上的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

State Pattern(状态模式):

      允许一个对象在其内部状态改变时改变它的行为。这个对象看起来似乎修改了它的类。

  能够让程序根据不同的外部情况来做出不同的响应,最直接的方法就是在程序中将这些可能发生的外部情况全部考虑到,使用if else语句来进行代码响应选择。但是这种方法对于复杂一点的状态判断,就会显得杂乱无章,容易产生错误;而且增加一个新的状态将会带来大量的修改。这个时候“能够修改自身”的状态模式的引入也许是个不错的主意。

  状态模式可以有效的替换充满在程序中的if else语句:将不同条件下的行为封装在一个类里面,再给这些类一个统一的父类来约束他们。来看一下状态模式的角色组成吧:

  1) 使用环境(Context)角色:客户程序是通过它来满足自己的需求。它定义了客户程序需要的接口;并且维护一个具体状态角色的实例,这个实例来决定当前的状态。

  2) 状态(State)角色:定义一个接口以封装与使用环境角色的一个特定状态相关的行为。

  3) 具体状态(Concrete State)角色:实现状态角色定义的接口。

  类图如下,结构非常简单也与策略模式非常相似。

 

什么时候该使用状态模式:

  1) 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

  2) 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。



/**
 *维护一个ConcreteState子类的一个实例,这个实例定义当前的状态
 */
public class Context {

    private State state;

    public void setState(State state) {
        this.state = state;
        System.out.println("当前状态是:" + state.GetType().Name);
    }

    public State getState() {
        return state;
    }

    public Context(State state) {
        this.state = state;
        System.out.println("初始状态是:"+state.GetType().Name);
    }

    public void Request() {
        state.Handle(this);
    }

}

/**
 *抽象状态类及其具体实现类
 */
public abstract class State {

   public abstract void Handle(Context context);

}

public class ConcreteStateA extends State {

    @override
    public void Handle(Context context){
        context.State = new ConcreteStateB();
    }

}

 

public class ConcreteStateB extends State {

    @override
    public void Handle(Context context) {
        context.State = new ConcreteStateC();
    }

}

public class ConcreteStateC extends State {

    @override
    public void Handle(Context context) {
        context.State = new ConcreteStateA();
    }

}

/**
 *客户端代码
 */
static void Main(string[] args){

    Context context = new Context(new ConcreteStateA());

    context.Request();

    context.Request();

    context.Request();

    Console.Read();

}

案例分析:

场景

银行账户根据余额可分为三种状态RedState,SilverState,GoldState,这些状态分别代表了透支帐户(overdrawn accounts),新开帐户(starter accounts),标准帐户(accounts in good standing)..如下图所示

 

RedState类:账号余额在范围【0.0,1000.0】表示处于处于SilverState。否则转换为其他状态。

if (balance < lowerLimit)

{

    account.State = new RedState(this);

}

else if (balance > upperLimit)

{

    account.State = new GoldState(this);

}

 

SilverState类:账号余额在范围【-100.0,0】表示处于处于RedState。否则转换为其他状态。

if (balance > upperLimit)

{

    account.State = new SilverState(this);

}

 

GoldState类:账号余额在范围【1000.0,10000000.0】表示处于处于GoldState。否则转换为其他状态。

if (balance < 0.0)

{

    account.State = new RedState(this);

}

else if (balance < lowerLimit)

{

    account.State = new SilverState(this);

}


/**
 *类Account,相当于Context类
 */
public class Account {

    private State _state;

    private string _owner;

    public Account(string owner) {
        this._owner = owner;            
        this._state = new SilverState(0.0, this);
    }

    public double getBalance {
        return _state.Balance; 
    }

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

    public void getState() {
        return _state; 
    }

    public void Deposit(double amount) {
        _state.Deposit(amount);
        System.out.println("Deposited {0:C} --- ", amount);
        System.out.println("Balance = {0:C}", this.Balance);
        System.out.println("Status = {0}",
        this._state.GetType().Name;
    }

    public void Withdraw(double amount) {
        _state.Withdraw(amount);
        System.out.println("Withdrew {0:C} --- ", amount);
        System.out.println(" Balance = {0:C}", this.Balance);
        System.out.println(" Status = {0}\n",
        this._state.GetType().Name;
    }

    public void PayInterest() {
        _state.PayInterest();
        System.out.println("Interest Paid --- ");
        System.out.println(" Balance = {0:C}", this.Balance);
        System.out.println(" Status = {0}\n",
        this.State.GetType().Name;
    }

}

/**
 *抽象状态类State及其具体状态类RedState,SilverState,GoldState
 */
public abstract class State {

    protected Account account;

    protected double balance;

    protected double interest;

    protected double lowerLimit;

    protected double upperLimit;

    public void setAccount(Account account) {
        this.account = account;
    }

    public Account getAccount() {
        return this.account;
    }

    public void setBalance(doublie balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return this.balance;
    }     
    
    public abstract void Deposit(double amount);

    public abstract void Withdraw(double amount);

    public abstract void PayInterest();

}

public class RedState extends State {

    private double _serviceFee;

    public RedState(State state) {
        this.balance = state.Balance;
        this.account = state.Account;
        Initialize();
    }

    private void Initialize() {
        interest = 0.0;
        lowerLimit = -100.0;
        upperLimit = 0.0;
        _serviceFee = 15.00;
    } 

    public override void Deposit(double amount) {
        balance += amount;
        StateChangeCheck();
    } 

    @override
    public void Withdraw(double amount) {
        amount = amount - _serviceFee;
        System.out.println("No funds available for withdrawal!");
    } 

    @override

    public void PayInterest() { // No interest is paid } 

    private void StateChangeCheck() { 
        if(balance > upperLimit) { 
            account.State = new SilverState(this); 
        } 
    }
}

public class SilverState extends State {
    public SilverState(State state) { 
        super(state.Balance, state.Account); 
    }

    public SilverState(double balance, Account account) { 
        this.balance = balance; 
        this.account = account; 
        Initialize(); 
    }

    private void Initialize() { 
        interest = 0.0; 
        lowerLimit = 0.0; 
        upperLimit = 1000.0; 
    } 

    @override
    public void Deposit(double amount) { 
        balance += amount; 
        StateChangeCheck(); 
    } 

    @override
    public override void Withdraw(double amount) { 
        balance -= amount; 
        StateChangeCheck(); 
    } 

    @override
    public void PayInterest() { 
        balance += interest * balance; 
        StateChangeCheck(); 
    } 

    private void StateChangeCheck() { 
        if (balance < lowerLimit) { 
            account.State = new RedState(this); 
        } else if (balance > upperLimit) { 
            account.State = new GoldState(this); 
        } 
    } 
}

public class GoldState extends State{ 
    public GoldState(State state) {
        super(state.Balance, state.Account);
    } 

    public GoldState(double balance, Account account){ 
        this.balance = balance; 
        this.account = account; 
        Initialize(); 
    } 
    
    private void Initialize() { 
        interest = 0.05; 
        lowerLimit = 1000.0; 
        upperLimit = 10000000.0; 
    } 
 
    public override void Deposit(double amount) { 
        balance += amount; 
        StateChangeCheck(); 
    } 
  
    @override
    public void Withdraw(double amount) { 
        balance -= amount; 
        StateChangeCheck(); 
    } 
  
    @override 
    public void PayInterest() {
        balance += interest * balance; 
        StateChangeCheck(); 
    }
 
    private void StateChangeCheck() { 
        if (balance < 0.0) { 
            account.State = new RedState(this); 
        } else if (balance < lowerLimit) { 
            account.State = new SilverState(this); 
        } 
    }
}

public static void Main(string[] args) { 
    Account account = new Account("Jim Johnson"); 
    account.Deposit(500.0); 
    account.Deposit(300.0); 
    account.Deposit(550.0); 
    account.PayInterest(); 
    account.Withdraw(2000.00); 
    account.Withdraw(1100.00);
}



dai ma mei you ce shi , jin wei shuo ming ye wu luo ji


状态VS策略

  仔细对比状态模式和策略模式,难免会产生疑问:这两个明明是一个东西嘛!下面我们就来分析下两者区别。

  首先我要声明,在实际应用中只要能够使得你的代码灵活漂亮起来,何必计较这些方方面面的差别呢?

  BrandonGoldfedder在《模式的乐趣》里是怎么说的:“strategy模式在结构上与state模式非常相似,但是在概念上,他们的目的差异非常大。区分这两个模式的关键是看行为是由状态驱动还是由一组算法驱动,这条规则似乎有点随意,但是在判断时还是需要考虑它。通常,State模式的“状态”是在对象内部的,Strategy模式的“策略”可以在对象外部,不过这也不是一条严格、可靠的规则。”

  我很同意Brandon Goldfedder的观点。这两个模式的划分,就在于使用的目的是不同的——策略模式用来处理算法变化,而状态模式则是处理状态变化(好玄乎阿)。

  策略模式中,算法是否变化完全是由客户程序开决定的,而且往往一次只能选择一种算法,不存在算法中途发生变化的情况。从《深入浅出策略模式》中的例子可以很好的看出。

  而状态模式如定义中所言,在它的生命周期中存在着状态的转变和行为得更改,而且状态变化是一个线形的整体;对于客户程序来言,这种状态变化往往是透明的。

状态模式与观察者模式的区别:
状态模式,也跟观察者模式一样,是一对多的模式。但观察者模式是“一”变了,所有的“多”也会更新。
状态模式,强调的是:“多”是“一”的各个状态,“一”的各个状态,进行不断的循环。
 
如何建立一与多的关系:
“多”,都是实现一个接口的。所以,在“一”的类中,声明的是“多”的接口;若“多”中要建立与“一”的关系,只须直接在类中声明“一”即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值