設計模式之責任鏈模式
職責鏈(責任鏈)模式 Chain of Responsibility
Intro
職責鏈(責任鏈)模式,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。
發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。
Sample
public class Request
{
public string RequestContent { get; set; }
public int RequestNum { get; set; }
}
public abstract class Manager
{
protected readonly string ManagerName;
protected Manager Superior;
protected Manager(string managerName) => ManagerName = managerName;
public void SetSuperior(Manager superior)
{
Superior = superior;
}
public abstract void RequestApplications(Request request);
}
public class CommonManager : Manager
{
public CommonManager(string managerName) : base(managerName)
{
}
public override void RequestApplications(Request request)
{
if (request.RequestNum <= 2)
{
Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准");
}
else
{
Superior?.RequestApplications(request);
}
}
}
public class Majordomo : Manager
{
public Majordomo(string managerName) : base(managerName)
{
}
public override void RequestApplications(Request request)
{
if (request.RequestNum <= 5)
{
Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准");
}
else
{
Superior?.RequestApplications(request);
}
}
}
public class GeneralManager : Manager
{
public GeneralManager(string managerName) : base(managerName)
{
}
public override void RequestApplications(Request request)
{
if (request.RequestNum <= 10)
{
Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天被批准");
}
else
{
Console.WriteLine($"{ManagerName}: {request.RequestContent} {request.RequestNum}天不被批准");
}
}
}
var manager = new CommonManager("金利");
var manager1 = new Majordomo("宗劍");
var manager2 = new GeneralManager("鍾精勵");
manager1.SetSuperior(manager2);
manager.SetSuperior(manager1);
var request = new Request()
{
RequestNum = 4,
RequestContent = "小菜請假"
};
manager.RequestApplications(request);
More
在職責鏈模式中,多個處理器(也就是剛剛定義中說的「接收對象」)依次處理同一個請求。一個請求先經過 A 處理器處理,然後再把請求傳遞給 B 處理器,B 處理器處理完後再傳遞給 C 處理器,以此類推,形成一個鏈條。鏈條上的每個處理器各自承擔各自的處理職責,所以叫作職責鏈模式(責任鏈模式)。
有沒有覺得 asp.net core 中請求管道中間件和上面的實例有點相像呢,
其實 asp.net core 中請求管道中間件的設計就是這種模式的變形,可以很靈活的處理請求
我封裝了一個 PipelineBuilder
(//www.cnblogs.com/weihanli/p/12700006.html) 用來輕鬆的構建中間件模式的代碼,
和 asp.net core 中間件的代碼幾乎一摸一樣,可以看下面的示例:
private class RequestContext
{
public string RequesterName { get; set; }
public int Hour { get; set; }
}
public static void Test()
{
var requestContext = new RequestContext()
{
RequesterName = "Kangkang",
Hour = 12,
};
var builder = PipelineBuilder.Create<RequestContext>(context =>
{
Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");
})
.Use((context, next) =>
{
if (context.Hour <= 2)
{
Console.WriteLine("pass 1");
}
else
{
next();
}
})
.Use((context, next) =>
{
if (context.Hour <= 4)
{
Console.WriteLine("pass 2");
}
else
{
next();
}
})
.Use((context, next) =>
{
if (context.Hour <= 6)
{
Console.WriteLine("pass 3");
}
else
{
next();
}
})
;
var requestPipeline = builder.Build();
foreach (var i in Enumerable.Range(1, 8))
{
Console.WriteLine();
Console.WriteLine($"--------- h:{i} apply Pipeline------------------");
requestContext.Hour = i;
requestPipeline.Invoke(requestContext);
Console.WriteLine("----------------------------");
Console.WriteLine();
}
}
Reference
- //github.com/WeihanLi/DesignPatterns/tree/master/BehaviorPattern/ChainOfResponsibilityPattern
- //www.cnblogs.com/weihanli/p/12700006.html