责任链模式
责任链使用场景
责任链代码实现
/// <summary>
/// 请假请求
/// </summary>
class LeaveRequest
{
/// <summary>
/// 请假天数
/// </summary>
public int LeaveDays { set; get; }
/// <summary>
/// 姓名
/// </summary>
public string Name { set; get; }
}
/// <summary>
/// 抽象管理类
/// </summary>
abstract class AbstractManagerLeaveHandler
{
public AbstractManagerLeaveHandler AbstractLeaveHandler { get; set; }
public abstract void HandlerLeaveRequest(LeaveRequest request);
}
/// <summary>
/// 部门经理
/// </summary>
class BMManagerLeaveHandler : AbstractManagerLeaveHandler
{
private readonly int allowedDays = 3; // 允许天数
private string handlerName; // 领导名称
public BMManagerLeaveHandler(string name)
{
this.handlerName = name;
}
public override void HandlerLeaveRequest(LeaveRequest request)
{
if (request.LeaveDays <= this.allowedDays)
{
Console.WriteLine("部门经理:" + this.handlerName + ",已批准请假;流程结束。");
return;
}
AbstractLeaveHandler?.HandlerLeaveRequest(request);
}
}
/// <summary>
/// 主管
/// </summary>
class ZGManagerLeaveHandler : AbstractManagerLeaveHandler
{
private readonly int allowedDays = 7; // 允许天数
private string handlerName; // 领导名称
public ZGManagerLeaveHandler(string name)
{
this.handlerName = name;
}
public override void HandlerLeaveRequest(LeaveRequest request)
{
if (request.LeaveDays <= this.allowedDays)
{
Console.WriteLine("主管:" + this.handlerName + ",已批准请假;流程结束。");
return;
}
AbstractLeaveHandler?.HandlerLeaveRequest(request);
}
}
/// <summary>
/// 总经理
/// </summary>
class ZManagerLeaveHandler : AbstractManagerLeaveHandler
{
private readonly int allowedDays = 20; // 允许天数
private string handlerName; // 领导名称
public ZManagerLeaveHandler(string name)
{
this.handlerName = name;
}
public override void HandlerLeaveRequest(LeaveRequest request)
{
if (request.LeaveDays <= this.allowedDays)
{
Console.WriteLine("总经理:" + this.handlerName + ",已批准请假;流程结束。");
return;
}
AbstractLeaveHandler?.HandlerLeaveRequest(request);
}
}
LeaveRequest lr = new();
lr.Name = "小明";
lr.LeaveDays = 8;
ZGManagerLeaveHandler zGManagerLeaveHandler = new ("张飞");
BMManagerLeaveHandler bMManagerLeaveHandler = new ("诸葛亮");
ZManagerLeaveHandler zManagerLeaveHandler = new("刘备");
bMManagerLeaveHandler.AbstractLeaveHandler = zManagerLeaveHandler;
zGManagerLeaveHandler.AbstractLeaveHandler = bMManagerLeaveHandler;
zGManagerLeaveHandler.HandlerLeaveRequest(lr);
Middleware实现原理
按责任链模式实现
创建请求类和中间件类。
/// <summary>
/// http上下文类(用于获取HttpRequest和HttpResponse)
/// </summary>
class HttpContext
{
public HttpRequest httpRequest { set; get; } // 请求输入类
public HttpResponse httpResponse { set; get; } // 请求响应输出
}
/// <summary>
/// http请求类
/// </summary>
class HttpRequest
{
/// <summary>
/// 请求url
/// </summary>
public string requestUrl;
}
/// <summary>
/// http响应类
/// </summary>
class HttpResponse
{
}
/// <summary>
/// 中间件抽象类
/// </summary>
abstract class Middleware
{
// 下一个中间件
public Middleware nextMiddleware { set; get; }
/// <summary>
/// 处理请求
/// </summary>
/// <param name="request"></param>
public abstract void HandlerRequest(HttpContext httpContext);
}
class Default404Middleware : Middleware
{
/// <summary>
/// 中间件是否终止条件
/// </summary>
private string token = "404";
public override void HandlerRequest(HttpContext httpContext)
{
Console.WriteLine($"执行默认404中间件");
// 判断请求url是否包含token,包含则终止
if (httpContext.httpRequest.requestUrl.Contains(token))
{
Console.WriteLine($"默认40中间件终止了");
return;
}
nextMiddleware?.HandlerRequest(httpContext);
}
}
class Default500Middleware : Middleware
{
/// <summary>
/// 中间件是否终止条件
/// </summary>
private string token = "500";
public override void HandlerRequest(HttpContext httpContext)
{
Console.WriteLine($"执行默认500中间件");
// 判断请求url是否包含token,包含则终止
if (httpContext.httpRequest.requestUrl.Contains(token))
{
Console.WriteLine($"默认500中间件终止了");
return;
}
nextMiddleware?.HandlerRequest(httpContext);
}
}
class HttpsMiddleware : Middleware
{
/// <summary>
/// 中间件是否终止条件
/// </summary>
private string token = "https";
public override void HandlerRequest(HttpContext httpContext)
{
Console.WriteLine($"执行默认https中间件");
// 判断请求url是否包含token,包含则终止
if (httpContext.httpRequest.requestUrl.Contains(token))
{
Console.WriteLine($"默认https中间件终止了");
return;
}
nextMiddleware?.HandlerRequest(httpContext);
}
}
像责任链模式一样调用
HttpContext httpContext = new();
HttpRequest httpRequest = new()
{
requestUrl = "500"
};
httpContext.httpRequest = httpRequest;
HttpsMiddleware httpsMiddleware = new();
Default404Middleware default404Middleware = new();
Default500Middleware default500Middleware = new();
httpsMiddleware.nextMiddleware = default404Middleware;
default404Middleware.nextMiddleware = default500Middleware;
httpsMiddleware.HandlerRequest(httpContext);
第一次改造
但是如果要想加入中间件,责任链这样的调用就会很麻烦,于是去改造代码,加入建造者模式。
/// <summary>
/// 封装中间件
/// </summary>
class Application
{
/// <summary>
/// 中间件链集合(中间件管道)
/// </summary>
private List<Middleware> middlewares = new List<Middleware>();
public Application(){ }
/// <summary>
/// 外部添加中间件
/// </summary>
/// <param name="middleware"></param>
public void AddMiddleware(Middleware middleware)
{
middlewares.Add(middleware);
}
/// <summary>
/// 创建动态中间链(通用)
/// 1、头部中间件
/// 2、中间变量
/// </summary>
/// <returns></returns>
public Middleware GetMiddleware()
{
// 1、头部节点
Middleware headerMiddleware = null;
// 2、中间变量
Middleware middlewareMiddle = null;
// 3、形成中间件链
foreach (var middleware in middlewares)
{
if (headerMiddleware == null)
{
middlewareMiddle = middleware;
headerMiddleware = middlewareMiddle;
}
else
{
middlewareMiddle.nextMiddleware = middleware;
middlewareMiddle = middleware;
}
}
return headerMiddleware;
}
}
/// <summary>
/// 中间件集合建造者
/// </summary>
class ApplicationBuilder
{
private Application application = new Application();
public void AddMiddleware(Middleware middleware)
{
application.AddMiddleware(middleware);
}
public Application Build()
{
return application;
}
}
上面代码中把中间件都添加到集合 middlewares 中,再通过 GetMiddleware 方法动态创建出中间件链。
以下在客户端调用。
HttpContext httpContext = new();
HttpRequest httpRequest = new()
{
requestUrl = "500"
};
httpContext.httpRequest = httpRequest;
ApplicationBuilder applicationBuilder = new ApplicationBuilder();
applicationBuilder.AddMiddleware(new HttpsMiddleware());
applicationBuilder.AddMiddleware(new Default404Middleware());
applicationBuilder.AddMiddleware(new Default500Middleware());
Application application = applicationBuilder.Build();
var middleware = application.GetMiddleware();
middleware.HandlerRequest(httpContext);
第二次改造
虽然责任链调用已经完成了封装,遵循了开闭原则,但是添加中间件 AddMiddleware 方法依然会随着中间件增加而增多,客户端代码不稳定。
于是我们使用了扩展方法,并引入 Startup 类。
static class HttpsMiddlewareExtension
{
public static ApplicationBuilder AddHttpsMiddleware(this ApplicationBuilder applicationBuilder)
{
applicationBuilder.AddMiddleware(new HttpsMiddleware());
return applicationBuilder;
}
}
static class Default404MiddlewareExtension
{
public static ApplicationBuilder AddDefault404Middleware(this ApplicationBuilder applicationBuilder)
{
applicationBuilder.AddMiddleware(new Default404Middleware());
return applicationBuilder;
}
}
static class Default500MiddlewareExtension
{
public static ApplicationBuilder AddDefault500Middleware(this ApplicationBuilder applicationBuilder)
{
applicationBuilder.AddMiddleware(new Default500Middleware());
return applicationBuilder;
}
}
/// <summary>
/// 启动类
/// </summary>
class Startup
{
public void Configure(ApplicationBuilder builder)
{
builder.AddHttpsMiddleware();
builder.AddDefault404Middleware();
builder.AddDefault500Middleware();
}
}
这样客户端代码就稳定了。
HttpContext httpContext = new();
HttpRequest httpRequest = new()
{
requestUrl = "500"
};
httpContext.httpRequest = httpRequest;
ApplicationBuilder applicationBuilder = new ApplicationBuilder();
Startup startup = new();
startup.Configure(applicationBuilder);
Application application = applicationBuilder.Build();
var middleware = application.GetMiddleware();
middleware.HandlerRequest(httpContext);
以后每次想添加中间件,只需要添加中间件类和扩展类,再往 Startup 类中加入就可以了,客户端调用代码完全不用动。