无废话C#设计模式之十六:State

意图

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

场景

我们在制作一个网上书店的网站,用户在书店买了一定金额的书后可以升级为银会员、黄金会员,不同等级的会员购买书籍有不同的优惠。你可能会想到可以在User类的BuyBook方法中判断用户历史消费的金额来给用户不同的折扣,在GetUserLevel方法中根据用户历史消费的金额来输出用户的等级。带来的问题有三点:

l 不用等级的用户给予的优惠比率是经常发生变化的,一旦变化是不是就要修改User类呢?

l 网站在初期可能最高级别的用户是黄金会员,而随着用户消费金额的累计,我们可能要增加钻石、白金等会员类型,这些会员的折扣又是不同的,发生这样的变化是不是又要修改User类了呢?

l 抛开变化不说,User类承担了用户等级判断、购买折扣计算等复杂逻辑,复杂的User类代码的可维护性会不会很好呢?

由此引入State模式,通过将对象和对象的状态进行分离,把对象状态的转化以及由不同状态产生的行为交给具体的状态类去做,解决上述问题。

示例代码

using System;

using System.Collections.Generic;

using System.Text;

namespace StateExample

{

    class Program

    {

        static void Main(string[] args)

        {

            User user = new User("zhuye");

            user.BuyBook(2000);

            user.BuyBook(2000);

            user.BuyBook(2000);

            user.BuyBook(2000);

        }

    }

    class User

    {

        private UserLevel userLevel ;

        public UserLevel UserLevel 

        {

            get { return userLevel ; }

            set { userLevel = value; }

        }

        private string userName;

        private double paidMoney;

        public double PaidMoney

        {

            get { return paidMoney; }

        }

        public User(string userName)

        {

            this.userName = userName;

            this.paidMoney = 0;

            this.UserLevel = new NormalUser(this);

        }

        public void BuyBook(double amount)

        {

            Console.WriteLine(string.Format("Hello {0}, You have paid ${1}, You Level is {2}.", userName, paidMoney, userLevel .GetType().Name));

            double realamount = userLevel .CalcRealAmount(amount);

            Console.WriteLine("You only paid $" + realamount + " for this book.");

            paidMoney += realamount;

            userLevel .StateCheck();

        }

    }

    abstract class UserLevel 

    {

        protected User user;

        public UserLevel (User user)

        {

            this.user = user;

        }

        public abstract void StateCheck();

        public abstract double CalcRealAmount(double amount);

    }

    class DiamondUser : UserLevel 

    {

        public DiamondUser(User user)

            : base(user) { }

        public override double CalcRealAmount(double amount)

        {

            return amount * 0.7;

        }

        public override void StateCheck()

        {

        }

    }

    class GoldUser : UserLevel 

    {

        public GoldUser(User user)

            : base(user) { }

        public override double CalcRealAmount(double amount)

        {

            return amount * 0.8;

        }

        public override void StateCheck()

        {

            if (user.PaidMoney > 5000)

                user.UserLevel = new DiamondUser(user);

        }

    }

    class SilverUser : UserLevel 

    {

        public SilverUser(User user)

            : base(user) { }

        public override double CalcRealAmount(double amount)

        {

            return amount * 0.9;

        }

        public override void StateCheck()

        {

            if (user.PaidMoney > 2000)

                user.UserLevel = new GoldUser(user);

        }

    }

    class NormalUser : UserLevel 

    {

        public NormalUser(User user)

            : base(user) { }

        public override double CalcRealAmount(double amount)

        {

            return amount * 0.95;

        }

        public override void StateCheck()

        {

            if (user.PaidMoney > 1000)

                user.UserLevel = new SilverUser(user);

        }

    }

}

时间: 2024-09-20 02:56:30

无废话C#设计模式之十六:State的相关文章

无废话C#设计模式之十九:Observer

意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新. 场景 这次不说游戏了,假设我们需要在一个Web页面上分页显示数据.首先需要一个分页控制器和一个显示数据的表格.开始,客户的需求很简单,需要两个向前翻页向后翻页的按钮作为控制器,还需要一个GridView来显示数据.你可能会这么做: l 在页面上放两个按钮和一个GridView控件 l 点击了下一页按钮判断是否超出了页面索引,如果没有的话更新GridView中的数据,然后更新控件的当前

无废话C#设计模式之十四:Template Method

意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 场景 模版方法是非常容易理解的设计模式,一来是因为它没有过多结构上的交错,二来是因为这种代码复用技术对于掌握OO知识的人来说非常容易可以想到,很可能你已经在很多地方运用了模版方法.在运用一些设计模式的时候常常也会一起运用模版方法,甚至有的设计模式本身就带有模版方法的思想. 今天,我们给出这样一个实际的例子.做过银行支付.支付宝支付的人都知道,

无废话C#设计模式之十八:Command

意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 场景 我们知道,网络游戏中的客户端需要不断把当前人物的信息发送到游戏服务端进行处理(计算合法性.保存状态到数据库等).假设有这样一种需求,在服务端收到客户端的请求之后需要判断两次请求间隔是不是过短,如果过短的话就考虑可能是游戏外挂,不但不执行当前请求还要把前一次请求进行回滚.暂且把问题简单化一点不考虑客户端和服务端之间的通讯来进行程序设计的话,你可能会创建一个Man类型,其中

无废话C#设计模式之十五:Strategy

意图 定义一系列的算法,把它们一个一个封装起来,并且使它们可相互替换.本模式使得算法可以独立于它的客户而变化. 场景 在开发程序的时候,我们经常会根据环境不同采取不同的算法对对象进行处理.比如,在一个新闻列表页面需要显示所有新闻,而在一个新闻搜索页面需要根据搜索关键词显示匹配的新闻.如果在新闻类内部有一个ShowData方法的话,那么我们可能会传入一个searchWord的参数,并且在方法内判断如果参数为空则显示所有新闻,如果参数不为空则进行搜索.如果还有分页的需求,那么还可能在方法内判断是否分

无废话C#设计模式之十二:Bridge

意图 将抽象部分与实现部分分离,使它们都可以独立的变化. 场景 还是说我们要做的网络游戏,多个场景需要扩充的问题我们已经采用了创建型模式来解决.现在的问题就是,不仅仅是游戏场景会不断扩充,而且游戏的模式也在不断扩充.比如,除了最基本的战斗模式之外,还会有道具模式,金币模式等. 对于这种在多个维度上都会有变化或扩充需求的项目来说,可以考虑引入桥接模式.或许你会说,不管是什么场景,不管什么模式,都可以是抽象场景的一个子类,但是,如果这样的话,4个场景和3种模式就会产生12个子类,而10个场景5种模式

无废话C#设计模式之十:Flyweight

意图 运用共享技术有效地支持大量细粒度的对象. 场景 在比较底层的系统或者框架级的软件系统中,通常存在大量细粒度的对象.即使细力度的对象,如果使用的数量级很高的话会占用很多资源.比如,游戏中可能会在无数个地方使用到模型数据,虽然从数量上来说模型对象会非常多,但是从本质上来说,不同的模型可能也就这么几个. 此时,我们可以引入享元模式来共享相同的模型对象,这样就可能大大减少游戏对资源(特别是内存)的消耗. 示例代码 using System; using System.Collections; us

云计算设计模式(十六)——优先级队列模式

云计算设计模式(十六)--优先级队列模式 优先发送到服务,以便具有较高优先级的请求被接收和高于一个较低优先级的更快速地处理请求.这种模式是在应用程序是有用的,它提供不同的服务级别保证或者针对独立客户. 背景和问题 应用程序可以委托给其他服务的具体任务;例如,为了执行后台处理或与其他应用程序或服务的整合.在云中,消息队列通常用于将任务委派给后台处理.在许多情况下,请求由服务接收的顺序是不重要的.然而,在某些情况下,可能需要优先考虑的具体要求.这些要求必须早于较低优先级的其他可能先前已发送由应用程序

无废话C#设计模式之二十二:总结(针对GOF23)

本文配套源码 比较 设计模式 常用程度 适用层次 引入时机 结构复杂度 Abstract Factory 比较常用 应用级 设计时 比较复杂 Builder 一般 代码级 编码时 一般 Factory Method 很常用 代码级 编码时 简单 Prototype 不太常用 应用级 编码时.重构时 比较简单 Singleton 很常用 代码级.应用级 设计时.编码时 简单 Adapter 一般 代码级 重构时 一般 Bridge 一般 代码级 设计时.编码时 一般 Composite 比较常用

无废话C#设计模式之二十:Mediator

意图 用一个中介对象来封装一系列对象的交互.中介者使得各对象不需要显式相互引用,从而使其松散耦合,而且可以独立地改变它们之间的交互. 场景 我们知道,一个网络游戏往往有很多大区.每一个大区可以是一组服务器,也可以是多组服务器,在这里假设一个大区是一组服务器.为了效率,一般每个大区都会有一个数据库,玩家的创建角色.充值.消费行为只是在这一个大区中有效.现在公司有了新的需求,那就是玩家的一些信息能在多个大区中共享.比如,在注册的时候就把玩家的账户信息写入多个信息共享的大区,玩家在某个大区中充值需要"