引言

我们在编程的时候,有时候会遇到,一个对象的行为动作会由对象的状态来决定的,也就是对象的行为是由状态来决定,如果对象的状态很多,那么也会由很多不同的行为,这时候我们一班会 if –else if—来判断对象的行为,当对象的行为或者状态发生变化时,就需要更改之前的代码,这样的设计就违背了开闭原则,而状态模式就是用来解决这样的问题的

状态模式的介绍

  • 状态模式的定义

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像改变了其类

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况,把状态的判断逻辑转移到表示不同状态的一系列类中,可以把负责的判断逻辑简单化,如果这个状态判断很简单,就没毕业使用“状态模式”了。

  • 状态模式的结构图

  • 状态模式的组成

(1)、环境角色(Context):也称上下文,定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
    (2)、抽象状态角色(State):定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。
    (3)、具体状态角色(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

  • 状态模式的代码实现

比如:支付宝中蚂蚁会员等级来说明,分为:大众会员、黄金会员、铂金会员、钻石会员四种, 不同的等级享受的服务不同,我们就拿免费体现的额度来比较一下,钻石会员体现的额度是100万,其他都是2万的额度,感觉这差别太大了,当额度使用完以后,可以使用蚂蚁积分兑换,兑换的规则是 大众会员 1积分兑换1元体现额度,黄金会员1积分兑换1.5的额度,铂金1积分兑换3元,钻石1积分兑换5元

第一版

 class Program
{
static void Main(string[] args)
{
Member m = new Member();
m.Membership = "大众会员";
m.Lines = true;
m.Withdrawal();
m.Membership = "黄金会员";
m.Lines = false;
m.Withdrawal();
m.Membership = "铂金会员";
m.Lines = true;
m.Withdrawal();
m.Membership = "钻石会员";
m.Lines = true;
m.Withdrawal();
}
}
public class Member
{
public string Membership { get; set; } //会员等级
public bool Lines { get; set; } //免费体现额度 public void Withdrawal()
{
if (Membership=="大众会员")
{
if (Lines)
{
Console.WriteLine("大众会员1积分可以兑换1元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
}
else if (Membership=="黄金会员")
{
if (Lines)
{
Console.WriteLine("黄金1积分可以兑换1.5元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
}
else if (Membership=="铂金会员")
{
if (Lines)
{
Console.WriteLine("铂金会员1积分可以兑换3元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
}
else
{
if (Lines)
{
Console.WriteLine("钻石1积分可以兑换5元提现额度");
}
else
{
Console.WriteLine("您有100的免费提现额度");
}
}
}
}

现在功能实现了,但是看仔细看看Member类中的Withdrawal方法,里面有很大分子判断,这就说明它的责任过大了,无论是任何状态,都需要通过它来改变,明显违背了“单一职责原则”、“开发封闭原则”。

第二版

    class Program
{
static void Main(string[] args)
{
Context m = new Context();
m.Action();
}
} public abstract class State
{
public abstract void Handle(Context context);
} public class PublicMember:State
{
public override void Handle(Context context)
{
if (context.Lines)
{
Console.WriteLine("大众会员1积分可以兑换1元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
context.SetState(new GoldMember());
context.Lines = true;
context.Action();
}
} public class GoldMember:State
{
public override void Handle(Context context)
{
if (context.Lines)
{
Console.WriteLine("黄金1积分可以兑换1.5元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
context.SetState(new PlatinumMember());
context.Lines = true;
context.Action();
}
} public class PlatinumMember : State
{
public override void Handle(Context context)
{
if (context.Lines)
{
Console.WriteLine("铂金会员1积分可以兑换3元提现额度");
}
else
{
Console.WriteLine("您还有免费的提现额度");
}
context.SetState(new DiamondMember());
context.Lines = true;
context.Action();
}
} public class DiamondMember : State
{
public override void Handle(Context context)
{
if (context.Lines)
{
Console.WriteLine("钻石1积分可以兑换5元提现额度");
}
else
{
Console.WriteLine("您有100的免费提现额度");
}
}
}
public class Context
{
public Context()
{
state = new PublicMember();
Lines = true;
}
private State state;
public string Membership { get; set; } //会员等级
public bool Lines { get; set; } //免费体现额度
public void SetState(State s)
{
state = s;
}
public void Action()
{
state.Handle(this);
}
}

状态模式的优缺点

  • 状态模式的优点
              (1)、封装了转换规则。
              (2)、枚举可能的状态,在枚举状态之前需要确定状态种类。
             (3)、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
              (4)、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
              (5)、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
  • 状态模式的缺点

(1)、状态模式的使用必然会增加系统类和对象的个数。
         (2)、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
         (3)、状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

总结

在对象的行动取决于本身的状态时,可以适用于状态模式,免去了过多的if–else判断,这对于一些复杂的和繁琐的判断逻辑有很好的帮助。但是使用状态模式,势必会造成更多的接口和类,对于非常简单的状态判断,可以不使用

c#设计模式系列:状态模式(State pattern)的更多相关文章

  1. 乐在其中设计模式(C#) - 状态模式(State Pattern)

    原文:乐在其中设计模式(C#) - 状态模式(State Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 状态模式(State Pattern) 作者:webabcd 介绍 允 ...

  2. 二十四种设计模式:状态模式(State Pattern)

    状态模式(State Pattern) 介绍允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它所属的类. 示例有一个Message实体类,对它的操作有Insert()和Get()方法, ...

  3. [设计模式] 20 状态模式 State Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对状态模式是这样说的:允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类.状态模式的重点在于状态转换,很多时候,对 ...

  4. 【UE4 设计模式】状态模式 State Pattern

    概述 描述 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类. 其别名为状态对象(Objects for States),状态模式是一种对象行为型模式. 有限状态机(FSMs) ...

  5. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  6. 设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  7. 状态模式-State Pattern(Java实现)

    状态模式-State Pattern 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. State接口 ...

  8. 北风设计模式课程---状态模式State(对象行为型)

    北风设计模式课程---状态模式State(对象行为型) 一.总结 一句话总结: 状态模式 具体状态的行为在具体的状态类中就解决,不用交给外部做判断.实质是将多条件判断弄成了多个类,在不同的类中做判断 ...

  9. 设计模式2——状态模式State

    参考链接: 设计模式之状态模式:https://www.cnblogs.com/haoerlv/p/7777789.html 设计模式系列之状态模式:https://www.jianshu.com/p ...

  10. 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)

    说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对“状态模式”并不陌生,因为我们之前使用到了状态模式进行重构.上一篇博客我们 ...

随机推荐

  1. Javascript中prototype属性详解 (存)

    Javascript中prototype属性详解   在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...

  2. 3DMAX 处理反面

    问题起源:从3DMAX导出一个模型为FBX后,在U3D中看到模型很奇怪的透视了,能看到背面看不到正面,这不法线问题,而是面反了. 即然是面反了,为什么在MAX中看起来是正确的呢? 应该是开启了双面模式 ...

  3. @JsonIgnore

    @JsonIgnore 避免取JSON对象时无限递归的问题,过滤掉一些不需要的属性,说明createdDate这个属性不需要转成json,放到getter方法前生效

  4. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 12—Support Vector Machines 支持向量机

    Lecture 12 支持向量机 Support Vector Machines 12.1 优化目标 Optimization Objective 支持向量机(Support Vector Machi ...

  5. Hadoop HA 机制学习

    一.Hadoop 系统架构 1.1 Hadoop1.x和Hadoop2.x 架构 在介绍HA之前,我们先来看下Hadoop的系统架构,这对于理解HA是至关重要的.Hadoop 1.x之前,其官方架构如 ...

  6. MYSQL 测试常用语句使用技巧

     终于有时间可以整理一下工作中常用的sql语句,基本的sql语句及增删改查就不说了.对于测试而言,经常用到的还是造数据,取随机数据和查询.比如造数据时,为了确保数据真实性,可能时间是随机的,用户是随机 ...

  7. yum基本用法与修改源

    一.yum简介 yum,是Yellow dog Updater Modified的简称,起初是由yellow dog这一发行版的开发者Terra Soft研发,用python写成,那时还叫做yup(y ...

  8. Cloud Foundry技术资料汇总

    来自:http://cnblog.cloudfoundry.com/2012/05/ 本文是Cloud Foundry的一个简单上手指南和资料汇总,内容将根据产品的发布定期更新. Cloud Foun ...

  9. 开启Windows8里面的Hyper-V虚拟机功能

    首先了解下什么是Hyper-V?也就是虚拟化技术,允许终端用户在同一台机器上运行多个操作系统,支持32位和64位系统,可以直接在Windows 8上创建自己的虚拟机.开启Hyper-V虚拟机需要更多的 ...

  10. C++ 模板 与 泛型编程

    C++ 模板 与 泛型编程 前言 模板有两种:类模板和函数模板 .模板是泛型编程的基础. 什么叫:泛型编程? 使用独立于特定类型的方式进行编程.也就是我们在编程的时候不明确的写上类型,而是使用一个模板 ...