Now when you look at the source code of some open source projects, you will find that there are many delegation functions everywhere, such as Func,Action,Predicate. It is true that the current C ා is becoming more and more mainstream on the way of functional programming, showing more and more power. Some of the classical design patterns used to be written can be slightly optimized under functional programming. In this article, we will talk about template methods.
1: Actual scenario
1. Template method definition
It is believed that this pattern is often used in normal development, and the definition is very simple. The algorithm skeleton is defined in the parent class, and some details in the skeleton are implemented by the corresponding subclass.
2. Business scenario
When pushing MMS to users, the company needs to connect with many MMS service providers, such as Bostone, helptone and union Vito. Each company has different requirements for the format of MMS submission. For example, Bostone and helptone require all content to be base64 encoded in the specified format and submitted in the past. Union Vito requires you to pack into a zip file stream in the specified format In the past, this is a classic template mode. The algorithm skeleton of MMS can be defined in the parent class, and the specific details can be implemented by each manufacturer's subclass. For the convenience of demonstration, the drawing is as follows:
The source code is as follows:
class MmsTemplate { public virtual string GetHeader() { return string.Empty; } public virtual string GetBody() { return string.Empty; } public virtual string GetTail() { return string.Empty; } public virtual void ProcessRequest() { Console.WriteLine($"1. MMS head:{GetHeader()}"); Console.WriteLine($"2. MMS:{GetBody()}"); Console.WriteLine($"3. MMS tail:{GetTail()}"); } } class ZhutongTemplate : MmsTemplate { public override string GetHeader() { return "I'm a helper!"; } public override string GetTail() { return "I'm all in one!"; } public override string GetBody() { return "I'm helping Tong Wei!"; } public override void ProcessRequest() { base.ProcessRequest(); } } class LianheweituoTemplate : MmsTemplate { public override string GetHeader() { return "I'm United Vito!"; } public override string GetTail() { return "I'm a united dimension!"; } public override string GetBody() { return "I'm United Vito tail!"; } public override void ProcessRequest() { base.ProcessRequest(); } }
Then the client can call the corresponding subclass according to the specified channel configuration to realize the MMS body construction of different manufacturers.
2: Delegate function
1. reflection
In the object-oriented programming language, this writing method can be called the standard. Let's first smooth the process. The subclass entry - > execute the parent method - > call the subclass method is shown in the figure below
A problem can be found in the above figure. When the parent class executes the algorithm skeleton, in order to be able to execute the subclass method again, the technology that must be used in object-oriented programming is polymorphism. In order to construct polymorphism, it is necessary to define a bunch of methods in the parent class, and then the subclass implements this bunch of methods. This is the getheader(), gettail(), as you can see, The origin of getbody() is a bit old.
2. Callback function
Take a closer look at this xmind figure. The method of mmmstemplate called by the ZhutongTemplate class. When the mmmstemplate class executes, it calls the method of ZhutongTemplate. The former is called call, the latter is called callback. If you don't understand, the former is called gift giving, and the latter is called gift returning... Yes, since I used to make callbacks with polymorphism, can I directly use the delegate function in C ා?
3. Transformation of formwork
Just look at the code. A thousand words is not worth a thousand words.
class MmsTemplate { protected Func<string> header; protected Func<string> body; protected Func<string> tail; public virtual void ProcessRequest() { Console.WriteLine($"1. MMS head:{header()}"); Console.WriteLine($"2. MMS:{header()}"); Console.WriteLine($"3. MMS tail:{tail()}"); } } class ZhutongTemplate : MmsTemplate { public override void ProcessRequest() { this.header = () => "I'm a helper!"; this.body = () => "I'm a helper"; this.tail = () => "I'm helping Tong Wei!"; base.ProcessRequest(); } } class LianheweituoTemplate : MmsTemplate { public override void ProcessRequest() { this.header = () => "I'm United Vito!"; this.body = () => "I am a united dimension extension"; this.tail = () => "I'm United Vito tail!"; base.ProcessRequest(); } }
From the above code, we can see that where polymorphism is needed, it is directly taken over by the delegate variable. Does it look much simpler than the previous polymorphism version.
Well, that's all. I'm looking forward to your discovery in more flexible ways~