e学编程之《设计模式》篇-状态模式

1384 人浏览 | 时间: 2015-07-27 16:17:15 | 作者: 软工人生
本文为大家讲解设计模式之状态模式。  

一、 为什么要用状态模式?相信不少朋友在学习设计模式时,都会感觉很困难,看着经典的教材,却味同嚼蜡,里面的术语、各种抽象概念让你感到迷茫,举步维艰,以至于放弃设计模式的学习。e学编程之《设计模式》篇为系列教程,根据笔者的学习、研究和开发经验撰写而成,旨在以通俗、易懂、生动的语言来讲解设计模式,并在讲解的过程中贯穿大量的实例,让初学设计模式的朋友拨云见日,从此觉得设计模式不再抽象,不再难学!笔者假设你已经具备了面向对象编程的基础知识,除些之外,对于理解本文其它的额外知识都不是必需的。鉴于笔者的水平有限,讲解的过程上可能会有一些错误和不足,也希望各位高手和老师批评指正,共同进步。

在一个软件中,某些对象往往不止有一种状态,例如在腾讯QQ中,一个用户有在线、隐身、忙碌等状态;在一个画图工具中,画笔可能有正方形、圆形和三角形等状态。

当这些对象处于不同的状态时,同一个操作有着不同的行为。以上述的的画图工具为例,当画笔处于正方形状态时,执行“画元素”这个操作,系统将会在画板上画一个正方形;而当画笔处于圆形状态时,执行“画元素”这个操作,系统所做的行为是在画板上画一个圆形。

当我们不使用状态模式时,如何处理上述这种情况呢?最简单的方法就是用多分支的条件语句,判断当前的画笔是正方形、圆形还是三角形状态,为每种情况编写不同的“画元素”函数。但是这样做并不“好”,体现在下面几个方面:

1) 使得系统的可扩展性和可维护性大大下降。当我们需要为我们系统中的某个元素增加新的状态时,我们要修改若干我们已有的代码,这样就使得系统的可扩展性和可维护性大大下降。继续以上述的画图工具为例,现在又需要增加菱形这种状态,那么此时我们就要在我们现有的代码中增加一个新的用数值定义的内部状态,然后在我们现有的条件分支中增加一个新的分支和操作。

2)使得代码中遍布看起来很相似的条件语句或case语句,代码非常庸肿冗余。上述的画图工具中画笔有三种状态,条件语句至少有三个分支或者三个case

3) 其状态仅表现为对一些变量的赋值,这不够明确。如果用013三个整型变量分别表示正方形、圆形和三角形三种状态,当我们当前的状态是正方形时,就给表示状态的数值型变量赋值为0,圆形和三角形类似。这样状态的表现不明确,代码的可读性和可理解性大大下降,容易引入各类错误和问题。

那们我们如何写出重用性、可读性、可理解性、可拓展性和可维护性更强的代码呢?这时我们就有必要使用状态模式来重构我们的代码。

二、什么是状态模式?

状态模式(State Pattern)允许一个对象在其内容状态改变时改变它的行为,对象看起来似乎修改了它的类[1]。
   笔者讲到上面这句话时,你可能已经感到很迷茫。别着急,这句话是从经典教材是摘录下来的,难理解是理所当然的。让我们继续以上述的画图工具为例来解释这句话。

首先解释“允许一个对象在其内容状态改变时改变它的行为”这句话。假设当前的画笔为正方形状态(这个画笔即是上面这句话中提到的“对象”),当用户执行“画元素”这个操作,此时系统的行为是在画板上为我们画一个正方形。而当我们将画笔切换为圆形状态时(即上面这句话中提到的“在其内容状态改变时”),此时系统的行为是画圆形。同样的操作(“画元素”),不同的行为(前者为画正方形,后者为画圆形)。这就是所谓的“允许一个对象在其内容状态改变时改变它的行为”。

那么“对象看起来似乎修改了它的类”这句话该如何理解呢?假设我们画笔类为CPen,我们定义该类的一个对象oPen。当该对象处于不同状态时,执行“画元素”这个操作(即调用该对象“画元素”成员函数:oPen.DrawElement())的行为是不同的。而CPen这个类和它的成员函数DrawElement()并没有任何变化,所以我们说“对象看起来似乎修改了它的类”。这句话包含两个意思,一是类操作的行为确实改变了,二是我们使用的是同一个类,调用的是该类的同一个方法,我们并没有修改该类。

这时你可能会迫不及待得问:“咦,这到底是怎么实现的呢?听起来好神奇椰!!!”别着急,下面我们就详细的讲解到底该如何实现状态模式。

三、如何实现状态模式?

我们以一个有趣的小程序为例来详细介绍如何实现一个状态模式(以C++为例)。
   青蛙王子有两种状态,一种是帅气的王子状态,另一种是丑陋的青蛙状态,而美丽的公主的一个吻就可以将青蛙王子从青蛙状态转换为王子状态。当青蛙王子处于青蛙状态时,其“说话”操作的行为是发出“呱呱呱”,处于王子状态时,其“说话”操作的行为是发出“美丽的公主,我爱你!”,如图1所示。即我们上面讲到的,一个对象
(青蛙王子)在其内容状态改变(从青蛙到王子)改变它的行为(“说话”操作从“呱呱呱”到“我爱你!美丽的公主!”)[1]。

请微信扫码阅读。
为防止恶意爬虫,
已开启反爬机制,
理解哟~~~~
标注
评论
站内搜
百度搜
传送到手机
手机扫码,识别文字,完成传送x
加载中...
标注内容x
加载中...
添加标注x
收藏 0 点赞 0