输出的结果:
状态模式:
当前时间:9点, 上午工作,精神百倍
当前时间:10点, 上午工作,精神百倍当前时间:12点 饿了, 午饭,犯困, 午休
当前时间: 13 点下午状态还不错,继续努力
当前时间: 14 点下午状态还不错,继续努力
当前时间17点,加班哦,疲惫之极
当前时间19点,加班哦,疲惫之极
当前时间:22点不行了,睡着了。
当前时间:22,点下班回家了。
职责链模式:
总经理:病假 数量10 被总经理批准
总监:病假 数量5 被总监批准
经理:病假 数量1被经理批准
总经理:加薪 数量500 被总经理批准
总经理:加薪 数量600 总经理不批准!
总经理:不是请假,加薪申请,工作流程错误,一律不批准!
总经理:病假 数量5 被总经理批准
组合模式:
结构图-北京总公司
---总公司人力资源部
---总公司财务部
---上海华东分公司
-----上海华东分公司人力资源部
-----上海华东分公司财务部
---南京办事处
-----南京办事处人力资源部
-----南京办事处财务部
---杭州办事处
-----杭州办事处人力资源部
-----杭州办事处财务部
职责
总公司人力资源部 员工招聘培训管理
总公司财务部 公司收支管理
上海华东分公司人力资源部 员工招聘培训管理
上海华东分公司财务部 公司收支管理
南京办事处人力资源部 员工招聘培训管理
南京办事处财务部 公司收支管理
杭州办事处人力资源部 员工招聘培训管理
杭州办事处财务部 公司收支管理
代码:
主类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WinServerTest1
{
public class IntoMain
{
public IntoMain()
{
}
/// <summary>
/// 状态模式
/// </summary>
public void StatePattern()
{
//执行开始
Work happyproject = new Work();
happyproject.Hour = 9;
happyproject.WriteProgram();
happyproject.Hour = 10;
happyproject.WriteProgram();
happyproject.Hour = 12;
happyproject.WriteProgram();
happyproject.Hour = 13;
happyproject.WriteProgram();
happyproject.Hour = 14;
happyproject.WriteProgram();
happyproject.Hour = 17;
happyproject.WriteProgram();
happyproject.TaskFinished = false;
happyproject.Hour = 19;
happyproject.WriteProgram();//并没有换状态。
happyproject.Hour = 22;
happyproject.WriteProgram();//换状态。
Console.Read();
}
/// <summary>
/// 职责链条模式
/// </summary>
public void ChainPattern()
{
//这里这么多请求,还可以做成事件的绑定方式。 当然不需要的话直接用LIST就可以,不要过度设计。
CommonManager jinli = new CommonManager("经理");
Majordomo zongjian = new Majordomo("总监");
GeneralMananger zhongjingli = new GeneralMananger("总经理");
jinli.SetSuperior(zongjian);
zongjian.SetSuperior(zhongjingli);
Request request = new Request();
request.RequestType = "请假";
request.RequestContent = "病假";
request.Number = 100;
jinli.RequestApplication(request); //所有流程构建后,从最初流程进入,并不知道具体管理负责的类。
Request request1 = new Request();
request1.RequestType = "请假";
request1.RequestContent = "病假";
request1.Number =10;
jinli.RequestApplication(request1);
Request request2 = new Request();
request2.RequestType = "请假";
request2.RequestContent = "病假";
request2.Number = 5;
jinli.RequestApplication(request2);
Request request3 = new Request();
request3.RequestType = "请假";
request3.RequestContent = "病假";
request3.Number = 1;
jinli.RequestApplication(request3);
Request request4 = new Request();
request4.RequestType = "加薪";
request4.RequestContent = "加薪";
request4.Number = 500;
jinli.RequestApplication(request4);
Request request5 = new Request();
request5.RequestType = "加薪";
request5.RequestContent = "加薪";
request5.Number = 600;
jinli.RequestApplication(request5);
Request request6 = new Request();
request6.RequestType = "旅游";
request6.RequestContent = "旅游";
request6.Number = 7;
jinli.RequestApplication(request6);
//更改当前的工作流程, 请假工作直接走向新的特殊流程,请假5天,直接走总经理流程,跳过总监。
jinli.SetSuperior(zhongjingli);
jinli.RequestApplication(request2);//请假5天,本来总监能批准,但是他不批,于是直接找总经理。
//问题1: 注意总经理的范围, 一开始是 >5 <10. 但是5到总经理那里就成了不能批准了,于是修改,改成0-10
//问题2: 这种职责链条的维护比较麻烦,比如,我这个需要做单独的处理, 下面还有很多需要做正常的处理,
// 还需要再次重新绑定整个序列。 如果很多种形式,则很麻烦。
// 维护方式,做接入和去除工作。和链表一样。
//例如, 做删除总监操作。 则把总监的后指向赋给经理。 但是需要首先做好基础定义。
// 在需要还原的话,就把 做插入方法, 把经理的后指向(总经理)给总监,把经理的指向赋成总监。
// 抽象类包装好此方法,将会好很多。
// 同时,单独需要的最好单独定义。 因为这种改动将会导致 链条混乱,除非有链条控制器。
Console.Read();
}
/// <summary>
/// 组合模式
/// </summary>
public void CombinePattern()
{
ConcreteCompany root = new ConcreteCompany("北京总公司");
root.Add(new HRDepartment("总公司人力资源部"));
root.Add(new FinanceDepartment("总公司财务部"));
ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
comp.Add(new HRDepartment("上海华东分公司人力资源部"));
comp.Add(new FinanceDepartment("上海华东分公司财务部"));
root.Add(comp);
ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
comp1.Add(new HRDepartment("南京办事处人力资源部"));
comp1.Add(new FinanceDepartment("南京办事处财务部"));
root.Add(comp1);
ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
comp2.Add(new HRDepartment("杭州办事处人力资源部"));
comp2.Add(new FinanceDepartment("杭州办事处财务部"));
root.Add(comp2);
Console.WriteLine("\n结构图");
root.Display(1);
Console.WriteLine("\n职责");
root.LineOfDuty();
Console.Read();
}
}
}
状态模式:StatePattern.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WinServerTest1
{
///<!--状态模式实例-->
#region 操作端
/// <summary>
/// 具体的工作对象,定义当前工作的属性与值, 利用State做状态对象。利用状态对象的参数传递WORK,针对此WORK做状态的切换。并且在切换中配置新的工作的属性与值,调用工作的状态执行方法。
/// </summary>
/// <remarks>
/// 1.关于工作对象中的各种状态和属性以及记录操作等,都可以在Work类中加入,并在状态对象中调用WORK对象实现。
/// 2.利用抽象类解耦,但是传递WORK对象也是一种耦合,这种耦合在面向对象中反而是必须的。就好像参数是object\int一样。
/// 3.状态模式解除的是在WORK中出现非常多的状态判断的情况。
/// </remarks>
public class Work
{
private State current;//因为是抽象类,所以解耦,而且抽象类指明是父子关系。接口指规范行为。
public Work() {
current = new ForenoonState();//状态子类
}
/// <summary>
/// 时间段
/// </summary>
private double hour;
public double Hour {
get { return hour; }
set { hour = value; }
}
/// <summary>
/// 任务--是否完成(整个工作流程)
/// </summary>
private bool finish = false;
public bool TaskFinished
{
get { return finish; }
set { finish = value; }
}
public void SetState(State s)//声明,方便以后使用,其实利用WriteProgram就可以做好状态传递。但是如果要扩展职责链条,有必要做扩展。
{
current = s;//状态切换
}
public void WriteProgram()
{
current.WriteProgram(this);//调用具体状态的State状态子类的方法。 传递WORK。
}
}
public abstract class State
{
public abstract void WriteProgram(Work k);
}
public class ForenoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 12)
{
Console.WriteLine("当前时间:{0}点, 上午工作,精神百倍",w.Hour);
}
else
{
w.SetState(new NoonState()); //按照指定顺序流程 调用WORK对象中的方法 更改下一个状态。
//也可以,在执行某个操作,通过操作判断是否进入下一个状态,还是结束。
//操作可以是多种 方法模块的不同组合,可以使用组合模式。
//还可以针对每个状态做各自的职责链条。 这个等职责模式搞出来之后再合并。
w.WriteProgram();
}
}
}
public class NoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 13) {
Console.WriteLine("当前时间:{0}点 饿了, 午饭,犯困, 午休",w.Hour);
}
else
{
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
}
public class AfternoonState : State
{
public override void WriteProgram(Work w)
{
if (w.Hour < 17)
{
Console.WriteLine("当前时间: {0} 点下午状态还不错,继续努力", w.Hour);
}
else
{
w.SetState(new EventingState());
w.WriteProgram();
}
}
}
public class EventingState : State
{//17-21
public override void WriteProgram(Work w)
{
//正常下班--客户端类中使用WORK对象,进行WORK对象的属性的更新。
if (w.TaskFinished) {
w.SetState(new RestState());
w.WriteProgram();
} else
{//加班
if (w.Hour < 21)
{
Console.WriteLine("当前时间{0}点,加班哦,疲惫之极",w.Hour);
}
else
{
w.SetState(new SleepingState());
w.WriteProgram();
}
}
}
}
public class SleepingState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("当前时间:{0}点不行了,睡着了。",w.Hour);//加班睡着
w.TaskFinished = true;
w.SetState(new EventingState()); //状态之间可以转向,但是主要不要做成环了就行了。
//通过改变WORK的属性,做操作。 如果WORK 的属性和标记更多,则可以在每个状态中做更多的控制。
//不过:状态模式本身就是为了解除过多的状态判断,如果里面再次嵌套,是否再次进行状态模式,这个要仔细考虑。
w.WriteProgram();
}
}
public class RestState : State
{
public override void WriteProgram(Work w)
{
Console.WriteLine("当前时间:{0},点下班回家了。",w.Hour);
}
}
#endregion
#region 客户端
//IntoMain
// Execute()
#endregion
}
职责链模式:ChainPattern.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WinServerTest1
{
//请求信息, 也是向下传递的。
public class Request
{
//申请类型
private string requestType;
public string RequestType
{
get { return requestType; }
set { requestType = value; }
}
//申请内容
private string requestContent;
public string RequestContent
{
get { return requestContent; }
set { requestContent = value; }
}
//数量
private int number;
public int Number
{
get { return number; }
set { number = value; }
}
}
/// <summary>
/// 管理者抽象类。。 每个负责不同职责功能 工作流程的的链条。
/// </summary>
public abstract class Manager
{
protected string name;
protected Manager superior;//向下的链条指向。 在部门中就是向上的领导。
public Manager(string name)
{
this.name = name;
}
public void SetSuperior(Manager superior) //更改向下链条。 与状态模式的WORK 不同的是, 本类做的是其他工作流的抽象父类定义。而WORK中状态改变非常频繁。
{
this.superior = superior;// 而这里基本是每个只定义一次。 利用Request的对象方法指向向下传递。
//即,状态模式传递一个WORK。职责模式通过指向下一个链条做连状。 与WORK中不断变化的指向向下类似。
//而,WORK中的状态改变是在具体的状态中指向下一条。
//链条模式是通过设置下一条直接做链接的改变。 可以在客户端控制。
//从程序设计中,我的程序确实需要很多状态变化。 但是每一个判断之后有可能就是组合成一种新的链条顺序。
//即,上一次需要某个环节, 本次不需要了。同是一个状态。
//这种情况, 我建议是 整体看做状态设计, 每个状态独立设计其不同判断下的链条组合。 链条走完了。可以走下一个状态。
//同样,因为状态的下次指向也无法确定,有可能从停电直接到结束。中间状态没有, 则状态也无法完全指定其下一个状态。
//则可以对于状态抽象类做类似。
//但是,状态模式主要是状态的分解。 职责模式主要是链条。 链条中的每个功能也有独立的,只是其切换是由链条控制的。
//请求信息也是向下传递的。不过不针对请求信息做 链条。 请求信息之做单独的封装数据传递。
//而状态模式做状态改变。 其中是 包状态封装到其内部。 职责是把 此请求做为参数不停的通过链条传递。
//只是侧重点不同, 其实request中如果封装做链条转换的方法,也可以使用。 当然这种使用是要切入 Manager 也就是
//链条中的抽象父类,中的属性之间做碰撞,然后 利用 职责链对象 做下一个链条的转换。
//又因为,我的状态之间是可以替换的。所以做个结合。 状态中加入职责链条。 WORK继续传递,保持其状态转换的功能,
//增加其状态指向的功能,具体状态中的数据打包成一个请求,然后进入此状态指定的请求链条, 做每一个操作。
//这里状态指向,在状态模式中靠状态类做, 现在改成WORK做,则WORK就类似与一种链条。
//链条其实可以改成状态模式, 比较是按照流程去做。这个思路确定,在具体实现中去构造把。
//链条的好处就是可以客户端指定其上级。
//批准,停止
//状态也好, 职责链条也好,总是有停止,而且停止的位置也有可能不同,停止后则链条不再继续。
//关于这个停止也要好好考虑考虑,其在状态中的停止代表不符合下一个状态进入的可能。
//其在职责链条的停止,代表链条执行完成或者出现特殊故障。 一般来说,链条如果是按照模块来划分的功能,不是特别的契合
//传递和职责覆盖结构, 拿来用就成了状态模式差不多的样子,要按流程走完。
//鉴于上面的分析, 在状态的部分,做成状态模式和职责链模式的结合, 在具体状态下工作要执行的模块,利用组合模式。
//为什么用组合模式, 因为在某个状态可以不去检测某种功能,而其他功能依然都是用,则各个状态都应该是小模块的组合。
//这里的组合与真正的组合模式不同, 真正的组合模式是嵌套,不断嵌套,但是最初也是这种简单的叠加。其实算是基本的活字印刷术。
//这样某个功能修改,改某一个类即可。
// 某个功能删除添加,在指定状态下的组合中修改即可。
//其状态改变也可以非常方面的修改指向。
}
abstract public void RequestApplication(Request request);
}
/// <summary>
/// 经理类
/// </summary>
public class CommonManager : Manager
{
public CommonManager(string name) :base(name)
{
}
public override void RequestApplication(Request request)//请求对象作为参数,传递
{
if (request.RequestType == "请假" && request.Number <= 2)//加入天数判断
{
Console.WriteLine("{0}:{1} 数量{2}被经理批准", name, request.RequestContent, request.Number);
}
else
{
if(superior!=null)
{
superior.RequestApplication(request);//向下传递参数, 而在客户端已经设置本类的指向。
}
}
}
}
/// <summary>
/// 总监
/// </summary>
class Majordomo : Manager
{
public Majordomo(string name) :base(name)
{ }
public override void RequestApplication(Request request)
{
if (request.RequestType == "请假" && request.Number <= 5)//加入天数判断
{
Console.WriteLine("{0}:{1} 数量{2} 被总监批准", name, request.RequestContent, request.Number);
}
else
{
if (superior != null) { superior.RequestApplication(request); }
}
}
}
//总经理
class GeneralMananger : Manager
{
public GeneralMananger(string name) : base(name) { }
public override void RequestApplication(Request request)
{
switch (request.RequestType)
{
case "请假":
if (request.Number > 0 && request.Number<=10)
Console.WriteLine("{0}:{1} 数量{2} 被总经理批准", name, request.RequestContent, request.Number);
else
Console.WriteLine("总经理:请详细说明情况!", name, request.RequestContent, request.Number);
//if病孕特殊情况,批准,不批准。
//传递回个人,个人结束流程。。
break;
case "加薪":
if ( request.Number <= 500)
{
Console.WriteLine("{0}:{1} 数量{2} 被总经理批准", name, request.RequestContent, request.Number);
}
else
{
Console.WriteLine("{0}:{1} 数量{2} 总经理不批准!", name, request.RequestContent, request.Number);
}
break;
default:
Console.WriteLine("总经理:不是请假,加薪申请,工作流程错误,一律不批准!", name, request.RequestContent, request.Number);
break;
}
}
}
}
组合模式:CombinePattern.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WinServerTest1
{
/// <summary>
/// 嵌套组合体现在抽象类中,分支类中叠加 抽象类。 即,实现抽象类、 根节点类、节点类3个类即可,其他的都是他们的组合。
/// 组合的好处是一个方面调用,其子类中的各自的方法也都立即响应。
/// 对我来说,嵌套的东西很少。 但是可以把每个状态做成一个组合,一个组合中组合所有的功能模块,当然功能模块多是平行的。
/// 至于嵌套可以先做出来,以后需要类似功能方便添加。
/// </summary>
public abstract class Company
{
protected string name;
public Company(string name) { this.name = name; }
//不同的子类都实现不同
public abstract void Add(Company com);//引用其子类,做组合嵌套使用
public abstract void Remove(Company com);
public abstract void Display(int depth);//显示
public abstract void LineOfDuty();//执行职责
}
/// <summary>
/// 具体公司类-- 树枝节点
/// </summary>
public class ConcreteCompany : Company
{
private List<Company> children = new List<Company>();
public ConcreteCompany(string name) : base(name) { }
public override void Add(Company com)
{
children.Add(com);
}
public override void Remove(Company com)
{
children.Remove(com);
}
/// <summary>
/// 显示层次
/// </summary>
/// <param name="depth"></param>
public override void Display(int depth)
{
Console.WriteLine(new String('-',depth)+name);
foreach(Company component in children) //这里 无法分辨是一个组合层次还是单组件。
{
component.Display(depth+2);// 但是利用这种层次+2,将每个组合向下逐渐 加两个字符。 嵌套的含义,非常的明显了。
}
}
/// <summary>
/// 履行职责
/// </summary>
public override void LineOfDuty()
{
foreach(Company component in children)
{
component.LineOfDuty();
}
}
}
class HRDepartment : Company
{
public HRDepartment(string name) : base(name) { }//继承抽象类的构造,否则可以自己写不同的构造函数。
public override void Add(Company com)
{
}
public override void Remove(Company com)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-',depth)+name);// 树叶与上面的树枝
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 员工招聘培训管理",name);
}
}
class FinanceDepartment : Company
{
public FinanceDepartment(string name) : base(name) { }
public override void Add(Company com)
{
}
public override void Remove(Company com)
{
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);// 树叶与上面的树枝
}
public override void LineOfDuty()
{
Console.WriteLine("{0} 公司收支管理", name);
}
}
}