输出的结果:
状态模式:
当前时间:9点, 上午工作,精神百倍
当前时间:10点, 上午工作,精神百倍当前时间:22,点下班回家了。
职责链模式:
组合模式:
结构图
代码:
主类:
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); } } }