首页 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
资讯 业界资讯 软件杂谈 编程开发 网站建设 网络观查 搜索引擎 移动应用 网站运营 网络地图
开发 移动开发 Web前端 架构设计 编程语言 互联网 数据库 系统运维 云计算 开发杂谈
[架构设计] 那些开发中用到的模式——访问者模式
那些开发中用到的模式——访问者模式
为了尽可能演示出Visitor 设计模式的强大之处,在此举一个开发中的场景
例如 开发A组 负责做log功能,而B组需要A组暴露一个API,可以拿到所有的log。
A组的代码实现可能是如下这样的:
public abstract class OrderLog{
public string Content {get;set;}
public OrderLog(string content){
Content = content;
}


}


public class PlaceOrderLog :OrderLog{
public PlaceOrderLog(string content,string orderedBy):base(content)
{
OrderedBy = orderedBy;
}
public string OrderedBy {get;set;}


}


public class MakePaymentLog :OrderLog{
public MakePaymentLog(string content, string paymentGateway, string payedBy):base(content)
{
PaymentGateway = paymentGateway;
PayedBy = payedBy;
}
public string PaymentGateway {get;set;}
public string PayedBy {get;set;}


}


public class OrderCompleteLog : OrderLog{
public OrderCompleteLog(string content, DateTime completeDate):base(content)
{
OrderCompleteDate = completeDate;
}
public DateTime OrderCompleteDate {get;set;}


}


public class OrderLogger{
public static OrderLogger Do
{
get
{
return new OrderLogger();
}
}


public IEnumerable<OrderLog> GetLogs(){
return new List<OrderLog>{
new PlaceOrderLog("place order log","ordered by"),
new MakePaymentLog("make payment log","paypal", "payedBy"),
new OrderCompleteLog("order complete log",DateTime.Now)
};


}


}

B组用法:
var logs = OrderLogger.Do.GetLogs();

B组新需求来了,需要A组再做一个API,可以把颜色信息加入LOG实体中,比如类型A返回红色,类型B返回绿色
A组有两个选择,再加一个API,还是把这个责任分发回B组,因为显然显示颜色的逻辑B组更熟悉。当然是分发责任,可如何分发,访问者模式来了。
1.在Log基类中添加一行:
public abstract T Visit<T>(ILogVisitor<T> visitor);

2.其他log子类中相应的实现它:
public override T Visit<T>(ILogVisitor<T> visitor){
return visitor.Visit(this);
}

为什么加这个方法?相当于给外界开一个入口,这样它们可以进来,然后把自身的信息传递给它们完成相应逻辑。
3.给B组一个接口(如果没有返回值,可以把T拿掉):
public interface ILogVisitor<T>{
T Visit(PlaceOrderLog log);
T Visit(MakePaymentLog log);
T Visit(OrderCompleteLog log);
}

为什么加这个接口?
1. 外部的访问者实现这个接口,就可以获取每个子类
2. 如果类层次变化,外部可以知道
3. 外部调用不用写大量的switch-case 或 if else臃肿的判断逻辑了
A组工作完成。接下来是B组要做的事情了——实现访问者接口。
实现也许是这样的:
public enum OrderLogColor{Red,Green}


public class OrderLogColorVisitor:ILogVisitor<OrderLogColor>{
public OrderLogColor Visit(PlaceOrderLog log){
return OrderLogColor.Red;
}


public OrderLogColor Visit(MakePaymentLog log){
return OrderLogColor.Green;
}


public OrderLogColor Visit(OrderCompleteLog log){
return OrderLogColor.Green;
}


}

逻辑很简单,对于不同的类型返回不同颜色。接下来就是调用部分:
var logs = OrderLogger.Do.GetLogs();
	////show colors
	var colorVisitor = new OrderLogColorVisitor();
	foreach(var log in logs){
	Console.WriteLine(log.Visit<OrderLogColor>(colorVisitor));
	}

可以看到,拿到一个日志集合后,循环过程只需调用Visit函数,就进入了相应的log类,然后在log类中,调用Visit函数完成Visit逻辑。执行结果:
Red
Green
Green

接下来,B组需要一个新的任务,对不同的日志类型,格式化显示不同的字符串。
于是只需要添加另一个Visitor:
public class OrderLogFormattedVisitor : ILogVisitor <string> {


public string Visit(PlaceOrderLog log){
return "this is place order log formatted information ";
}


public string Visit(MakePaymentLog log){
return "this is make payment log formatted information ";
}


public string Visit(OrderCompleteLog log){
return "this is order complete log formatted information ";
}


}

调用:
var logs = OrderLogger.Do.GetLogs();
var formatVisitor = new OrderLogFormattedVisitor();
	foreach(var log in logs){
	Console.WriteLine(log.Visit<string>(formatVisitor));
	}

看出访问者模式的作用了吗?它把职责隔离的同时,有效的封装了变化。在以上例子中,A组只负责做LOG API,而B组负责拿到LOG后的事情。 在开发中会经常遇到相互调用的情况,每当这个时候,首先考虑职责分配,用接口隔离工作,决定调用的入口。这便是访问者模式的强大之处。
以下是完整的代码:
void Main()
{
	var logs = OrderLogger.Do.GetLogs();
	////show colors
	var colorVisitor = new OrderLogColorVisitor();
	foreach(var log in logs){
	Console.WriteLine(log.Visit<OrderLogColor>(colorVisitor));
	}
	////show formatted logs
	var formatVisitor = new OrderLogFormattedVisitor();
	foreach(var log in logs){
	Console.WriteLine(log.Visit<string>(formatVisitor));
	}
}


////team A job
public abstract class OrderLog{
public string Content {get;set;}
public OrderLog(string content){
Content = content;
}


public abstract T Visit<T>(ILogVisitor<T> visitor);


}


public class PlaceOrderLog :OrderLog{
public PlaceOrderLog(string content,string orderedBy):base(content)
{
OrderedBy = orderedBy;
}
public string OrderedBy {get;set;}


public override T Visit<T>(ILogVisitor<T> visitor){
return visitor.Visit(this);
}


}


public class MakePaymentLog :OrderLog{
public MakePaymentLog(string content, string paymentGateway, string payedBy):base(content)
{
PaymentGateway = paymentGateway;
PayedBy = payedBy;
}
public string PaymentGateway {get;set;}
public string PayedBy {get;set;}


public override T Visit<T>(ILogVisitor<T> visitor){
return visitor.Visit(this);
}
}


public class OrderCompleteLog : OrderLog{
public OrderCompleteLog(string content, DateTime completeDate):base(content)
{
OrderCompleteDate = completeDate;
}
public DateTime OrderCompleteDate {get;set;}


public override T Visit<T>(ILogVisitor<T> visitor){
return visitor.Visit(this);
}


}


public class OrderLogger{
public static OrderLogger Do
{
get
{
return new OrderLogger();
}
}


public IEnumerable<OrderLog> GetLogs(){
return new List<OrderLog>{
new PlaceOrderLog("place order log","ordered by"),
new MakePaymentLog("make payment log","paypal", "payedBy"),
new OrderCompleteLog("order complete log",DateTime.Now)
};


}




}


////now team B want a API , return different log color based on different type
////team A give team B a visitor interface , ask them to implement




public interface ILogVisitor<T>{
T Visit(PlaceOrderLog log);
T Visit(MakePaymentLog log);
T Visit(OrderCompleteLog log);
}


////team B come out with the implementations


public enum OrderLogColor{Red,Green}


public class OrderLogColorVisitor:ILogVisitor<OrderLogColor>{
public OrderLogColor Visit(PlaceOrderLog log){
return OrderLogColor.Red;
}


public OrderLogColor Visit(MakePaymentLog log){
return OrderLogColor.Green;
}


public OrderLogColor Visit(OrderCompleteLog log){
return OrderLogColor.Green;
}


}


////in future 
////if team B want more , just implement the ILogVisitor interface 
////for example : formatted log


public class OrderLogFormattedVisitor : ILogVisitor <string> {


public string Visit(PlaceOrderLog log){
return "this is place order log formatted information ";
}


public string Visit(MakePaymentLog log){
return "this is make payment log formatted information ";
}


public string Visit(OrderCompleteLog log){
return "this is order complete log formatted information ";
}


}


////whats next 
////whenever team B want , he just add more visitor to accept different log types returned from teamA



 此文从网络中自动搜索生成,不代表本网站赞成被搜索网站的内容或立场    查看原文
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年7日历
2018-7-20 14:38:18
 
  网站联系 软件世界网-www.sjsjw.com ©2014 蜀ICP备06016416号 三峰网旗下网站