(44)C#设计模式——状态者模式(State Pattern)

介绍

每个对象都有其对的状态,而每个状态有对应一些相应的行为,如果多个对象有多个状态,那么就会对应很多种行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前的代码。这样设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化不再依赖于对象内部的行为。

定义

状态模式:允许一个对象在其内部状态改变时自动改变其行为,对象看起来就像是改变了它的类。

结构

既然状态者模式是对已有对象的状态进行抽象,则自然就有抽象状态者类和具体状态者类,而原来已有对象需要保存抽象状态者类的引用,通过调用抽象状态者的行为来改变已有对象的行为。
在这里插入图片描述

  • Account类:维护一个State类的一个实例,该实例标识着当前对象的状态
  • State类:抽象状态类,定义了一个具体状态类需要实现的行为约定
  • SilveStater,GoldState,RedState类:具体状态类,实现抽象状态类的每个行为。

实现

下面,就以银行账户的状态来实现状态者模式。银行账户根据余额可分为RedState、SliverState和GoldState。这些状态分别代表透支账号、新开账户和标准账户。账号余额在【-100.0,0.0】范围表示处于RedState状态,账号余额在【0.0 , 1000.0】范围表示处于SilverState,账号在【1000.0, 100000.0】范围表示处于GoldState状态。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _35StatePatternDemo
{
    public class Account
    {
        public State State { get; set; }
        public string Owner { get; set; }
        public Account(string owner)
        {
            this.Owner = owner;
            this.State = new SilverState(0.0, this);
        }
        //余额
        public double Balance { get { return State.Balance; } }
        //存钱
        public void Deposit(double amount)
        {
            State.Deposit(amount);
            Console.WriteLine("存款金额为 {0:C}——", amount);
            Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
            Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
            Console.WriteLine();
        }
        //取钱
        public void Withdraw(double amount)
        {
            State.Withdraw(amount);
            Console.WriteLine("取款金额为 {0:C}——", amount);
            Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
            Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
            Console.WriteLine();
        }
        //获得利息
        public void PayInterest()
        {
            State.PayInterest();
            Console.WriteLine("Interest Paid --- ");
            Console.WriteLine("账户余额为 =:{0:C}", this.Balance);
            Console.WriteLine("账户状态为: {0}", this.State.GetType().Name);
            Console.WriteLine();
        }

    }
    //抽象状态类
    public abstract class State
    {
        public Account Account { get; set; }
        public double Balance { get; set; }//余额
        public double Interest { get; set; }//利率
        public double LowerLimit { get; set; }//上限
        public double UpperLimit { get; set; }//下限

        public abstract void Deposit(double amount);//存钱
        public abstract void Withdraw(double amount);//取钱
        public abstract void PayInterest();//获得利息
    }
    //Red Satae 以为者Account透支了
    public class RedState : State
    {
        public RedState(State state)
        {
            this.Balance = state.Balance;
            this.Account = state.Account;
            Interest = 0.00;
            LowerLimit = -100.00;
            UpperLimit = 0.00;
        }
        public override void Deposit(double amount)
        {
            Balance += amount;
            StateChangeCheck();
        }

        public override void PayInterest()
        {
            //没有利息
        }

        public override void Withdraw(double amount)
        {
            Console.WriteLine("没钱可以取了");
        }
        private void StateChangeCheck()
        {
            if (Balance > UpperLimit)
            {
                Account.State = new SilverState(this);
            }
        }
    }
    //SilverState 没有利息得
    public class SilverState : State
    {
        public SilverState(State state) : this(state.Balance, state.Account)
        {

        }
        public SilverState(double balance, Account account)
        {
            this.Balance = balance;
            this.Account = account;
            Interest = 0.0;
            LowerLimit = 0.0;
            UpperLimit = 1000.00;
        }
        public override void Deposit(double amount)
        {
            Balance += amount;
            StateChangeCheck();
        }

        public override void PayInterest()
        {
            Balance += Interest * Balance;
            StateChangeCheck();
        }

        public override void Withdraw(double amount)
        {
            Balance += amount;
            StateChangeCheck();
        }
        private void StateChangeCheck()
        {
            if(Balance<LowerLimit)
            {
                Account.State = new RedState(this);
            }
            else if(Balance>UpperLimit)
            {
                Account.State = new GoldState(this);
            }
        }
    }
    public class GoldState:State
    {
        public GoldState(State state)
        {
            this.Balance = state.Balance;
            this.Account = state.Account;
            Interest = 0.05;
            LowerLimit = 1000.00;
            UpperLimit = 1000000.00;
        }
        public override void Deposit(double amount)
        {
            Balance += amount;
            StateChangeCheck();
        }
        public override void Withdraw(double amount)
        {
            Balance -= amount;
            StateChangeCheck();
        }
        public override 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);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Account account = new Account("Bob");

            account.Deposit(1000.0);
            account.Deposit(200.0);
            account.Deposit(600.0);

            account.PayInterest();
            
            account.Withdraw(2000.00);
            account.Withdraw(500.00);
        }
    }
}

引用状态者模式完善中介者模式方案

在上一篇文章中,介绍了中介者模式存在的问题,信息问题请参看上一篇文章。下面利用两种模式来解决上一篇文章中提到的问题。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _34MediatorPatternDemo
{ 
	public abstract class AbstractCardPatner
    {
        public int MoneyCount { get; set; }
        public AbstractCardPatner()
        {
            MoneyCount = 0;
        }
        public abstract void ChangeCount(int Count, AbstractMediator mediator);
    }
    //具体牌友类
    public class ParterA : AbstractCardPatner
    {
        //依赖与抽象中介者对象
        public override void ChangeCount(int Count, AbstractMediator mediator)
        {
            mediator.ChangeCount(Count);
        }
    }
    public class ParterB : AbstractCardPatner
    {
        //依赖与抽象中介者对象
        public override void ChangeCount(int Count, AbstractMediator mediator)
        {
            mediator.ChangeCount(Count);
        }
    }
    //抽象状态类
    public abstract class State
    {
        protected AbstractMediator meditor;
        public abstract void ChangeCount(int count);
    }
    //A状态类
    public class AWinState : State
    {
        public AWinState(AbstractMediator concretemeditor)
        {
            this.meditor = concretemeditor;
        }
        public override void ChangeCount(int count)
        {
            foreach(AbstractCardPatner p in meditor.list)
            {
                ParterA a = p as ParterA;
                if(a!=null)
                {
                    a.MoneyCount += count;
                }
                else
                {
                    p.MoneyCount -= count;
                }
            }
        }
    }
    public class BWinState : State
    {
        public BWinState(AbstractMediator concretemeditor)
        {
            this.meditor = concretemeditor;
        }
        public override void ChangeCount(int count)
        {
            foreach (AbstractCardPatner p in meditor.list)
            {
                ParterB b = p as ParterB;
                if(b!=null)
                {
                    b.MoneyCount += count;
                }
                else
                {
                    p.MoneyCount -= count;
                }
            }
        }
    }
    //初始化状态类
    public class InitState : State
    {
        public InitState()
        {
            Console.WriteLine("游戏才刚刚开始,暂时还有玩家胜出");
        }
        public override void ChangeCount(int count)
        {
            //
            return;
        }
    }
    //抽象中介者类
    public abstract class AbstractMediator
    {
        public List<AbstractCardPatner> list = new List<AbstractCardPatner>();
        public State State { get; set; }
        public AbstractMediator(State state)
        {
            this.State = state;
        }
        public void Enter(AbstractCardPatner partner)
        {
            list.Add(partner);
        }
        public void Exit(AbstractCardPatner partner)
        {
            list.Remove(partner);
        }
        public void ChangeCount(int count)
        {
            State.ChangeCount(count);
        }
       
    }
    //具体中介者类
    public class MediatorPater : AbstractMediator
    {
        public MediatorPater(State initState) : base(initState)
        {
        }
     
    }
    //客户端类
    class Program
    {
        static void Main(string[] args)
        {
            AbstractCardPatner A = new ParterA();
            AbstractCardPatner B = new ParterB();
            //初始化钱
            A.MoneyCount = 20;
            B.MoneyCount = 30;
            AbstractMediator mediator = new MediatorPater(new InitState());
            //A B 进入平台游戏
            mediator.Enter(A);
            mediator.Enter(B);
            //A赢了
            mediator.State = new AWinState(mediator);
            mediator.ChangeCount(5);
            Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是25
            Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是25

            Console.WriteLine("继续");                                 
            //继续打,B赢了
            mediator.State = new BWinState(mediator);
            mediator.ChangeCount(10);
            Console.WriteLine("A 现在的钱是:{0}", A.MoneyCount);// 应该是15
            Console.WriteLine("B 现在的钱是:{0}", B.MoneyCount); // 应该是35
        }
    }

应用场景

  • 当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一些列类中,可以吧复杂化的判断逻辑简化
  • 当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式

优缺点

  • 优点
    将状态判断逻辑放到每个状态类里面,可以简化判断逻辑
    当有新状态出现时,可以通过添加新的状态类来进行扩展,扩展性好
  • 缺点
    如果状态过多的话,会产生非常多的状态类,增加了开销

总结

状态者模式是对对象状态的抽象,从而把对象中对状态复杂的判断逻辑归到各个状态类里面,从而简化判断逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值