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 ...
随机推荐
- Array的基本操作
准备饿补基础技术,先来个数组的总结. 1 .合并操作 concat : var C = A.concat(B); 用A数组合并B数组,生成新的C数组. 循环插入 ...
- vertical-align 和 img属性 和 鼠标样式
一.vertical-align 一)定义:定义行内元素的基线相对于该所在基线的垂直对齐.(只针对行类块inline/inline-block/<img>,块级不适用!) 二)语法: 三 ...
- Anaconda+用conda创建python虚拟环境
Anaconda+用conda创建python虚拟环境 Anaconda与conda区别 conda可以理解为一个工具,也是一个可执行命令,其核心功能是包管理与环境管理.包管理与pip的使用类似,环境 ...
- C# TreeView 控件的综合使用方法
1.概述 该篇文章开发使用的语言c#,环境visualstudio2010,sql数据库.主要内容包括: (1)treeView控件添加根节点.子节点的基本方法,节点的删除. (2)把treeView ...
- ES6 数组的扩展
1. Array.from() Array.from()将类数组(array-like)对象与可遍历的对象转化为数组并返回. 下面是一个类数组 let arr = { '0':'a', '1':'b' ...
- lesson - 1 笔记 网络连接 /putty 密钥登陆
---笔记 一.网络连接配置 1. 查看电脑ip 地址: ifconfig -a 2. 自动获取ip 地址: dhclient 默认BOOTPROTO=dhcp 和真机同一网段 3. 手动配置 ...
- Oracle 用户操作表权限
grant select any table to xxx 将使得xxx用户能够查看到所有用户的表:正确的授权不能是这样: 用户是隔离表的schema,授权时..
- Linux(CentOS6.5)修改系统市区被中国标准时间(北京时间)
本文地址http://comexchan.cnblogs.com/ ,作者Comex Chan,尊重知识产权,转载请注明出处,谢谢! 备份时区配置文件 cp /etc/localtime /etc/l ...
- 关于模拟登陆微博(PC)
微博模拟登陆 1.基类对象的方法建立一个类__init__初始化方法,接收username和password. class launcher(): def __init__(self, usernam ...
- git 的回退
今天下午写了一下午的代码给合并没了 然后晚上觉得还是要好好学习一下git的使用 推荐几个git的教程 https://www.liaoxuefeng.com/wiki/0013739516305929 ...