C#学习笔记-状态模式
题目1:通过代码描述每一天的不同时间段的工作效率
分析:
首先确定,工作状态指正在工作,或者以及下班这些情况,而这些情况所受影响的因素包括:当前时间以及任务是否已经完成。所以在Work中需要两个属性:hour和finish。然后根据这两个属性直接判断当前的工作状态即可。
实现:
class Program
{
static void Main(string[] args)
{
//紧急项目
Work emergencyProject = new Work();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.Finish = false;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram(); Console.Read();
}
public class Work
{
private int hour;
private bool finish = false; public int Hour
{
get { return hour; }
set { hour = value; }
}
public bool Finish
{
get { return finish; }
set { finish = value; }
}
/// <summary>
/// 根据时间来判断当前的工作状态如何
///
/// 方法过长
/// </summary>
public void WriteProgram()
{
if (hour < )
{
Console.WriteLine("当前时间:{0}点 上午工作,精神百倍", hour);
}
else if (hour < )
{
Console.WriteLine("当前时间:{0}点 饿了,午饭;犯困,午休", hour);
}
else if (hour < )
{
Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", hour);
}
else
{
if (finish)
{
Console.WriteLine("当前时间:{0}点 下班回家了", hour);
}
else
{
if (hour < )
{
Console.WriteLine("当前时间:{0}点 加班哦,疲惫至极", hour);
}
else
{
Console.WriteLine("当前时间:{0}点 不行了,睡着了。", hour);
}
}
}
}
}
}
题目2:从1中可以很明显的看出WriteProgram()函数几乎承载了所有的判断处理,且函数函数过长,所以在Work类中违背了“单一职责原则"。
分析:
面向对象设计就是希望做到代码的责任分解,在这个情况中,我们将所有的判断全部添加在了WriteProgram()一个函数中,不仅是函数冗长,如果我临时添加新的情况,可能对原来判断有出入的时间也会造成很多麻烦,对于将来的修改百害而无一利。
所以我们需要根据情况来分解函数和类。
本题目中,我们需要获得当前的工作状态,而这个的直接影响因素包括时间Hour和是否已经完成任务TaskFinished。
所以我们根据当前的时间可以很明显的分为不同时间段,也就是WriteProgram()的if,else都可以自己单独拥有一个类,他们都继承于同一个抽象类State即可。
然后我们初始化直接进入ForenoonState类,毕竟每天早上的时间不会变,如果当前时间不再是早上,那么我们就需要进入下一个时间段进行判断,所以在ForenoonState类中我们需要加入判断,如果当前时间满足早上的时间段,显示工作状态,如果当前时间不再是早上的时间段,那么我们进入下一个时间段,以此类推,找到我们当前时间段的工作状态。

实现:
class Program
{
static void Main(string[] args)
{
//紧急项目
Work emergencyProject = new Work();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.TaskFinished = false;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram();
emergencyProject.Hour = ;
emergencyProject.WriteProgram(); Console.Read();
}
public class Work
{
private int hour;
private bool finish = false;
private State current;
//初始化进入的时候是上午工作状态
public Work()
{
current = new ForenoonState();
}
public int Hour
{
get { return hour; }
set { hour = value; }
}
public bool TaskFinished
{
get { return finish; }
set { finish = value; }
} public void SetState(State s)
{
current = s;
}
public void WriteProgram()
{
current.WriteProgram(this);
}
}
/// <summary>
/// 抽象状态
/// </summary>
public abstract class State
{
public abstract void WriteProgram(Work w);
}
/// <summary>
/// 上午工作状态
///
/// 逻辑是:根据时间推移,上午工作后,移至中午午饭时间
/// </summary>
public class ForenoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0} 上午工作,精神百倍", w.Hour);
}
else
{
w.SetState(new NoonState());
w.WriteProgram();
}
}
}
/// <summary>
/// 中午工作状态
///
/// 逻辑是:根据时间推移,午休时间后,移至下午工作时间
/// </summary>
public class NoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0} 饿了,午饭;犯困,午休", w.Hour);
}
else
{
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
}
/// <summary>
/// 下午工作状态
///
/// 逻辑是:根据时间推移,下午工作后,移至晚间工作状态
/// </summary>
public class AfternoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < )
{
Console.WriteLine("当前时间:{0} 下午状态还不错,继续努力", w.Hour);
}
else
{
w.SetState(new EveningState());
w.WriteProgram();
}
}
}
/// <summary>
/// 晚间工作状态
///
/// 逻辑是:已完成工作的可以准点下班,移至下班休息状态
/// 未完成工作的继续加班:这里又分为未超过人体承受能力的(21小时)就继续加班(此处已是最底层,没有再多加其他的操作了)
/// 超过21小时的将移至睡眠状态
/// </summary>
public class EveningState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
w.SetState(new RestState());
w.WriteProgram();
}
else
{
//最底层,不要再次调用,会无限往复的
if (w.Hour < )
{
Console.WriteLine("当前时间:{0} 加班哦,疲惫至极", w.Hour);
}
else
{
w.SetState(new SleepingState());
w.WriteProgram();
}
}
}
}
/// <summary>
/// 睡眠状态
///
/// 最底层,不要再次调用,会无限往复的
/// </summary>
public class SleepingState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour);
}
}
/// <summary>
/// 下班休息状态
///
/// 最底层,不要再次调用,会无限往复的
/// </summary>
public class RestState : State
{
public override void WriteProgram(Work w)
{
if (w.TaskFinished)
{
Console.WriteLine("当前时间:{0}点 下班回家", w.Hour);
}
}
}
}
总结:
这里用到的就是状态模式(State):当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的调节表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以吧复杂的判断逻辑简化。
状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。
C#学习笔记-状态模式的更多相关文章
- 《Head First 设计模式》学习笔记——状态模式
在软件开发过程中.应用程序可能会依据不同的情况作出不同的处理. 最直接的解决方式是将这些全部可能发生的情况全都考虑到.然后使用if... ellse语句来做状态推断来进行不同情况的处理. 可是对复杂状 ...
- 学习笔记——状态模式State
状态模式,主要是用于存在大量case判断的操作执行,同时这些case依赖于对象的状态,那么就可以将大量的case判断封装为独立的类. Context: -state,当前状态对象. ChangeSta ...
- Java设计模式学习记录-状态模式
前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...
- 《Head first设计模式》学习笔记 – 迭代器模式
<Head first设计模式>学习笔记 – 迭代器模式 代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. 爆炸性新闻:对象村餐厅和对象村煎饼屋合并了!真是个 ...
- 设计模式 笔记 状态模式 State
//---------------------------15/04/28---------------------------- //State 状态模式----对象行为型模式 /* 1:意图: ...
- 《Head First 设计模式》学习笔记——迭代模式 + 组合模式
迭代模式设置共生死亡,一般来说.我们只是想实现一个集,我们需要的同时提供这个集合的迭代器,喜欢java中间Collection.List.Set.Map等,这些集合都有自己的迭代器.假如我们要实现一个 ...
- 学习笔记——解释器模式Interpreter
解释器模式,其实就是编译原理中的语法解释器,如果用在项目中,可以用于实现动态脚本的解析,也就是说项目可以支持用户脚本扩展. 但实际上,这种运行时解释,效率很慢,如果不是很需要的话,不建议使用. 一种简 ...
- 学习笔记——备忘录模式Memento
备忘录模式,可以将当前状态保存,并随时恢复. Originator存在状态state,当需要保存此状态时,通过CreateMemento创建一个备忘录对象Memento保存此状态:而需要恢复相应状态时 ...
- C#学习笔记-备忘录模式
什么是备忘录模式? 备忘录模式(Memento):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态. 这样以后就可将该对象恢复到原先保存的状态. 备忘录模式的组成 Orig ...
随机推荐
- 关于redis的使用
距离上次写博客有两三个月了,这段时间去了新公司上班,忙了很多.接手了一个项目,刚好用到redis,先总结下遇到的问题(跟redis相关的问题): 1.列表问题 举例:展示商品列表,但是要先展示运营置顶 ...
- [UWP]了解模板化控件(7):支持Command
以我的经验来说,要让TemplatedControl支持Command的需求不会很多,大部分情况用附加属性解决这个需求会更便利些,譬如UWPCommunityToolkit的HyperlinkExte ...
- 【java提高】---ArrayList源码
ArrayList源码 一.定义 public class ArrayList<E> extends AbstractList<E> implements List<E& ...
- C# 委托高级应用----线程——创建无阻塞的异步调用(二)
了解IAsyncResult 现在我们已经了解,EndInvoke可以给我们提供传出参数与更新后的ref参数:也可以向我们导出异步函数中的异常信息.例如,我们使用BeginInvoke调用了异步函数S ...
- scala写算法-从后缀表达式构造
一个例子,比如ab+cde+**,这是一个后缀表达式,那么如何转换为一棵表达式树呢? 先上代码,再解释: object Main extends App{ import Tree.node def i ...
- 转战Hexo
从之前的转战farbox,到现在又转战Hexo,真是不折腾不成魔.要说farbox有什么不好,可能唯一的不好就是它要求与Dropbox关联吧,这对于大部分国内用户来说是无法接受的,写文章之前一想到还要 ...
- php-自动过滤、自动填充、自动验证
最近又学到了一些新技巧,和大家分享下. 第一.当一个表单有很大内容时,我们在表单处理页面接收这些表单的值的时候就会重复 接收,于是就有了自动过滤的解决之法(核心就是把数据表里需要的字段接收) 首先:我 ...
- 学习rollup.js模块文件打包
学习rollup.js模块文件打包 一:rollup 是什么?Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码. webpack 和 Rollup 对比不同点 ...
- zepto的返回顶部scrollTop的动画解决方法
写移动端的时候,引入的zepto.js里的animate不包括scrollTop,所以返回顶部的时候,没有动画的效果.这里我使用的是setInterval的方法.代码详情如下 <!DOCTYPE ...
- selenium爬取百度图片
一:简介 通过selenium模块,模拟火狐浏览器进行搜索下载操作. 二:脚本内容 # -*- coding:utf-8 -*- # 百度图片自动爬去 # Chrome浏览器类似,设置其options ...