Use Case:
We have this hypothetical reporting system where 2 entities are involved Report Generator & Report.
Report Generator:
- Report generator would have a single behavior.
- It should take 2 inputs as integers.
- It Returns a string back as an output which is basically the report presentation.
(So, basically above 2 point forms the contract that need to be fulfilled by any report generator)
Report:
- Report should take report generator object or report generation logic in the form of function as an input.
- Give call to the report generator by passing input1 & input2.
- Get the string Output back from generator.
- Will have the functionality to write the Output to console or file system.
Whenever, I introduce a new Report Generator, neither Report entity nor existing Report Generator's, should be modified.
Take a pause
Think about the solution
?
Think again
Scroll down for the solution
...
...
...
...
...
...
Solution
Run the below code in Linqpad (https://www.linqpad.net/), to see it working.
void Main() | |
{ | |
Report r = new Report(new LineChart()); | |
r.GenerateAndWiteToConsole(10, 20); | |
r = new Report(new PieChart()); | |
r.GenerateAndWiteToConsole(20,30); | |
r = new Report(new StackChart()); | |
r.GenerateAndWiteToConsole(30,40); | |
Report2 r2 = new Report2((input1, input2) => {return $"This is a report with values {input1} & {input2}";}); | |
r2.GenerateAndWiteToConsole(10, 20); | |
r2 = new Report2((input1, input2) => {return $"This is a report with values {input1} & {input2}";}); | |
r2.GenerateAndWiteToConsole(20,30); | |
r2 = new Report2((input1, input2) => {return $"This is a report with values {input1} & {input2}";}); | |
r2.GenerateAndWiteToConsole(30,40); | |
} | |
public interface IReportGenerator | |
{ | |
string Report(int input1, int input2); | |
} | |
public class LineChart : IReportGenerator | |
{ | |
public string Report(int input1, int input2) | |
{ | |
return $"This is the output from {this.GetType().Name}, with values {input1} & {input2}"; | |
} | |
} | |
public class PieChart: IReportGenerator | |
{ | |
public string Report(int input1, int input2) | |
{ | |
return $"This is the output from {this.GetType().Name}, with values {input1} & {input2}"; | |
} | |
} | |
public class StackChart : IReportGenerator | |
{ | |
public string Report(int input1, int input2) | |
{ | |
return $"Some report with value with values {input1} & {input2}"; | |
} | |
} | |
public class Report{ | |
private IReportGenerator reportGenerator; | |
public Report(IReportGenerator reportGenerator) | |
{ | |
this.reportGenerator = reportGenerator; | |
} | |
public void GenerateAndWiteToConsole(int input1, int input2) | |
{ | |
var output = reportGenerator.Report(input1, input2); | |
Console.WriteLine(output); | |
} | |
public void GenerateAndWriteToFileSystem(int input1, int input2, string filePath) | |
{ | |
var output = reportGenerator.Report(input1, input2); | |
File.WriteAllText(filePath,output); | |
} | |
} | |
public class Report2 | |
{ | |
private Func<int,int,string> reportGenerator; | |
public Report2(Func<int,int,string> reportGenerator) | |
{ | |
this.reportGenerator = reportGenerator; | |
} | |
public void GenerateAndWiteToConsole(int input1, int input2) | |
{ | |
var output = reportGenerator(input1, input2); | |
Console.WriteLine(output); | |
} | |
public void GenerateAndWriteToFileSystem(int input1, int input2, string filePath) | |
{ | |
var output = reportGenerator(input1, input2); | |
File.WriteAllText(filePath, output); | |
} | |
} |
Motivation
Generally every one understands the theoretical aspect of Delegates and Interfaces, but when it comes to actual use of the same, beginner's lacks the understanding of when such constructs need be used and in which scenario. This problem based illustration might be of some help to understand the concept better.
Happy Coding !!
Top comments (0)