C#设计模式之行为型模式详解
这里列举行为型模式·到此23种就列完了···这里是看着菜鸟教程来实现··,他里边列了25种,其中过滤器模式和空对象模式应该不属于所谓的23种模式
责任链模式:为请求创建一个接收者对象的链,对请求的发送者和接收者进行解耦,大部分用于web中吧。。
task中的continuewith和微软的tpl数据流应该是类似这种模式的实现吧
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; //责任链模式 namespace exerciseprj.dsignmode { public abstract class abstractlogger { public static int info = 1; public static int debug = 2; public static int error = 3; protected int level; //责任链中的下一个对象 protected abstractlogger nextlogger; public void setnextlogger(abstractlogger next) { nextlogger = next; } public void logmessage(int level,string message) { if(this.level<=level) { write(message); } if(nextlogger!=null) { nextlogger.logmessage(level, message); } } protected abstract void write(string message); } public class consolelogger : abstractlogger { public consolelogger(int level) { this.level = level; } protected override void write(string message) { console.writeline("standard console::logger: " + message); } } public class errorlogger : abstractlogger { public errorlogger(int level) { this.level = level; } protected override void write(string message) { console.writeline("error console::logger: " + message); } } public class filelogger : abstractlogger { public filelogger(int level) { this.level = level; } protected override void write(string message) { console.writeline("file::logger: " + message); } } }
命令模式(command pattern):请求以命令的形式执行,cad的的命令应该就是以这种方式执行的·二次开发的时候通过特性标识和继承他的接口来添加命令,非常方便
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; //命令模式 namespace exerciseprj.dsignmode { public interface iorder { void execute(); } public class stock { private string name = "abc"; private int quantity = 10; public void buy() { console.writeline("stock name:{0},quantity:{1},bought",name,quantity); } public void sell() { console.writeline("stock name:{0},quantity:{1}sold", name, quantity); } } //请求类 public class buystock : iorder { private stock abcstock; public buystock(stock abcstock) { this.abcstock = abcstock; } public void execute() { abcstock.buy(); } } //继承接口的实体 public class sellstock : iorder { private stock abcstock; public sellstock(stock abcstock) { this.abcstock = abcstock; } public void execute() { abcstock.sell(); } } //命令调用类 public class broker { private list<iorder> orderlist = new list<iorder>(); public void takeorder(iorder order) { orderlist.add(order); } public void placeorders() { foreach (iorder order in orderlist) { order.execute(); } orderlist.clear(); } } }
解释器模式:就是实现一种表达式接口,c#的各种表达式就是这种实现吧··这玩意跟富文本编辑器一样是个大坑吧··,做好了确实很好使,一不小心就得跪
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; //解释器模式 namespace exerciseprj.dsignmode { public interface expression { bool interpret(string context); } public class terminalexpression : expression { private string data; public terminalexpression(string data) { this.data = data; } public bool interpret(string context) { if (context.contains(data)) { return true; } return false; } } public class orexpression : expression { private expression expr1 = null; private expression expr2 = null; public orexpression(expression expr1, expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } public bool interpret(string context) { return expr1.interpret(context) || expr2.interpret(context); } } public class andexpression : expression { private expression expr1 = null; private expression expr2 = null; public andexpression(expression expr1, expression expr2) { this.expr1 = expr1; this.expr2 = expr2; } public bool interpret(string context) { return expr1.interpret(context) && expr2.interpret(context); } } }
迭代器模式(iterator pattern):.net自带接口···,直接实现就行了··注意又泛型接口和非泛型接口··非泛型接口迭代对象返回的是object,泛型接口返回的直接就是对象了,还有通过yield的简化写法不用额外去实现ienumerator接口
using system; using system.collections; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public class iteratorex : ienumerable //<iteratorex> { public string name; private list<iteratorex> list = new list<iteratorex>(); //public ienumerator<iteratorex> getenumerator() //{ // foreach (var l in list) // { // yield return l; // } //} public void setlist(list<iteratorex> data) { list = data; } ienumerator ienumerable.getenumerator() { foreach (var l in list) { yield return l; } //return new iteratorexenum(list.toarray()); } } public class iteratorexenum : ienumerator { private iteratorex[] list; private int position = -1; public iteratorexenum(iteratorex[] data) { list = data; } public object current { get { try { return list[position]; } catch (indexoutofrangeexception) { throw new invalidoperationexception(); } } } public bool movenext() { position++; return position < list.length; } public void reset() { position = -1; } } }
中介者模式(mediator pattern):用一个中介对象封装一些对象的交互,中介者使对象不用显式的互相引用,mvc和mvp 的c和p都是类似这玩意的实现吧
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { //中介类 public class chatroom { public static void showmessage(user user, string msg) { console.writeline(new datetime().tostring()+"["+ user.name + "] : " + msg); } } public class user { public string name { get; set; } public user(string name) { name = name; } public void sendmessage(string message) { chatroom.showmessage(this, message); } } }
备忘录模式(memento pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存,
大部分支持回退的操作场景下应该都是这种模式··之前做的软件中有画图的操作···支持后退,实现方式非常简单粗暴··,直接吧图层的画图对象克隆一份保存··只支持5还是10步,讲道理这么实现确实有点那啥了···
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public class memento { public string state { get; } public memento(string state) { state = state; } } public class originator { public string state { get; set; } public memento savestatetomemento() { return new memento(state); } public void getstatefrommemento(memento memento) { state = memento.state; } } public class caretaker { private list<memento> mementolist = new list<memento>(); public void add(memento state) { mementolist.add(state); } public memento get(int index) { return mementolist[index]; } } }
观察者模式(observer pattern):.net自带的有接口提供来实现观察者模式···这里照着msdn来实现一遍,自带的接口里边还实现了资源的释放··,之前并发编程里边的rx也是这个模式的具体实现·
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; //观察者模式 namespace exerciseprj.dsignmode { public class subject: iobservable<subject> { public int state {get; set;} public subject(int state) { state = state; } private list<iobserver<subject>> observers = new list<iobserver<subject>>(); public idisposable subscribe(iobserver<subject> observer) { if (!observers.contains(observer)) observers.add(observer); return new unsubscriber(observers, observer); } private class unsubscriber : idisposable { private list<iobserver<subject>> _observers; private iobserver<subject> _observer; public unsubscriber(list<iobserver<subject>> observers, iobserver<subject> observer) { this._observers = observers; this._observer = observer; } public void dispose() { if (_observer != null && _observers.contains(_observer)) _observers.remove(_observer); } } public void tracklocation(subject ob) { console.writeline("start"); foreach (var observer in observers) { if (ob==null) observer.onerror(new exception("unknowexeption")); else observer.onnext(ob); } } public void endtransmission() { foreach (var observer in observers.toarray()) if (observers.contains(observer)) observer.oncompleted(); observers.clear(); } } public class binaryobserver : iobserver<subject> { public void oncompleted() { console.writeline("complete"); } public void onerror(exception error) { console.writeline(error.message); } public void onnext(subject value) { console.writeline("binary string: " + convert.tostring(value.state, 2)); } } public class octalobserver : iobserver<subject> { public void oncompleted() { console.writeline("complete"); } public void onerror(exception error) { console.writeline(error.message); } public void onnext(subject value) { console.writeline("octal string: " + convert.tostring(value.state, 8)); } } public class hexaobserver : iobserver<subject> { public void oncompleted() { console.writeline("complete"); } public void onerror(exception error) { console.writeline(error.message); } public void onnext(subject value) { console.writeline("hex string: " + convert.tostring(value.state,16)); } } }
状态模式(state pattern):当对象内部状态发生改变时,行为也跟着改变
这个模式是为了解决类里边的大量if和swicth语句,讲道理例子写的有点怪···主体是context
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public class context { public state state { get; set; } public context() { state = null; } } public interface state { void doaction(context context); } public class startstate : state { public void doaction(context context) { console.writeline("player is in start state"); context.state = this; } public override string tostring() { return "start state"; } } public class stopstate : state { public void doaction(context context) { console.writeline("player is in stop state"); context.state = this; } public override string tostring() { return "stop state"; } } }
空对象模式(null object pattern):就是吧对空值的判断定义一个啥也不做的实体对象出来··c#的nullable就是这个的实现···这玩意不在23种设计模式里边···
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public abstract class abstractcustomer { public abstract bool isnull(); public abstract string name { get; } } public class realcustomer : abstractcustomer { public override string name { get; } public realcustomer(string name) { name = name; } public override bool isnull() { return false; } } public class nullcustomer : abstractcustomer { public override string name { get { return "not available in customer database"; } } public override bool isnull() { return true; } } public class customerfactory { public static string[] names = {"rob", "joe", "julie"}; public static abstractcustomer getcustomer(string name) { if(names.contains(name)) { return new realcustomer(name); } return new nullcustomer(); } } }
策略模式(strategy pattern):定义一系列算法,封装成类,可以相互替换,通过构造不同的类,执行不同的操作。这样做方便调用,添加新的算法也方便,
最后加了自己之前对这个模式的奇葩写法
using system; using system.collections.generic; using system.linq; using system.reflection; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public interface istrategy { int dooperation(int num1, int num2); } public class operationadd : istrategy { public int dooperation(int num1, int num2) { return num1 + num2; } } public class operationsubstract : istrategy { public int dooperation(int num1, int num2) { return num1 - num2; } } public class operationmultiply : istrategy { public int dooperation(int num1, int num2) { return num1 * num2; } } public class contextex { private istrategy strategy; public contextex(istrategy strategy) { this.strategy = strategy; } public int executestrategy(int num1, int num2) { return strategy.dooperation(num1, num2); } //奇葩的写法简单粗暴 private dictionary<string, func<int, int, int>> funcs = new dictionary<string, func<int, int, int>>(); public int executestrategy(string name, int num1, int num2) { if(funcs.count==0) { //反射写法 var assembly = assembly.getexecutingassembly(); var types = assembly.gettypes(); foreach (var t in types) { if (t.getinterface("istrategy") != null) { var instance = assembly.createinstance(t.fullname) as istrategy; funcs.add(t.name, instance.dooperation); } } //直接添加 //funcs.add("operationadd", new func<int, int, int>((n1, n2) => { return n1 + n2; })); //funcs.add("operationsubstract", new func<int, int, int>((n1, n2) => { return n1 - n2; })); //funcs.add("operationmultiply", new func<int, int, int>((n1, n2) => { return n1 * n2; })); } return funcs[name](num1, num2); } } }
模板模式(template pattern):.net的泛型就是这个模式的实现吧··照着模子写就行了
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public abstract class game { public abstract void initialize(); public abstract void startplay(); public abstract void endplay(); //模板 public void play() { //初始化游戏 initialize(); //开始游戏 startplay(); //结束游戏 endplay(); } } public class cricket : game { public override void endplay() { console.writeline("cricket game finished!"); } public override void initialize() { console.writeline("cricket game initialized! start playing."); } public override void startplay() { console.writeline("cricket game started. enjoy the game!"); } } }
访问者模式(visitor pattern):在被访问的类里边加一个对外提供接待访问的接口
把数据结构和对应的操作分开·添加操作很容易,但是如果结构变化多的化,改起来就麻烦了··
没研究没用过····
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace exerciseprj.dsignmode { public interface icomputerpartvisitor { void visit(computer computer); void visit(mouse mouse); void visit(keyboard keyboard); void visit(monitor monitor); } public interface icomputerpart { void accept(icomputerpartvisitor computerpartvisitor); } public class keyboard : icomputerpart { public void accept(icomputerpartvisitor computerpartvisitor) { computerpartvisitor.visit(this); } } public class monitor : icomputerpart { public void accept(icomputerpartvisitor computerpartvisitor) { computerpartvisitor.visit(this); } } public class mouse : icomputerpart { public void accept(icomputerpartvisitor computerpartvisitor) { computerpartvisitor.visit(this); } } public class computer : icomputerpart { icomputerpart [] parts; public computer() { parts = new icomputerpart[] { new mouse(), new keyboard(), new monitor() }; } public void accept(icomputerpartvisitor computerpartvisitor) { for (int i = 0; i < parts.length; i++) { parts[i].accept(computerpartvisitor); } computerpartvisitor.visit(this); } } public class computerpartdisplayvisitor : icomputerpartvisitor { public void visit(computer computer) { console.writeline("displaying computer."); } public void visit(mouse mouse) { console.writeline("displaying mouse."); } public void visit(keyboard keyboard) { console.writeline("displaying keyboard."); } public void visit(monitor monitor) { console.writeline("displaying monitor."); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。