CSharp: Visitor Pattern in donet core 3
/// <summary>
/// 访问者模式 Visitor Pattern
/// geovindu,Geovin Du eidt
/// </summary>
interface IEmployee
{
/// <summary>
/// To set an employee name
/// </summary>
string Name { get; set; }
/// <summary>
/// To set an employee department
/// </summary>
string Dept { get; set; }
/// <summary>
/// To set an employee designation
/// </summary>
string Designation { get; set; }
/// <summary>
/// To display an employee details
/// </summary>
void DisplayDetails();
/// <summary>
///Newly added for this example
///To set years of Experience
///</summary>
double Experience { get; set; }
/// <summary>
/// Newly added for this example
/// </summary>
/// <param name="visitor"></param>
void Accept(IVisitor visitor);
}
/// <summary>
/// Leaf node
/// </summary>
class Employee : IEmployee
{
/// <summary>
///
/// </summary>
public string Name { get; set; }
/// <summary>
///
/// </summary>
public string Dept { get; set; }
/// <summary>
///
/// </summary>
public string Designation { get; set; }
/// <summary>
///
/// </summary>
public double Experience { get; set; }
/// <summary>
/// Details of a leaf node
/// </summary>
public void DisplayDetails()
{
Console.WriteLine($"姓名:{Name} 工作在 {Dept} 部门.描述:{Designation}.经历 : {Experience} 年.");
}
/// <summary>
///
/// </summary>
/// <param name="visitor"></param>
public void Accept(IVisitor visitor)
{
visitor.VisitEmployees(this);
}
}
/// <summary>
/// Non-leaf node
/// </summary>
class CompositeEmployee : IEmployee
{
/// <summary>
///
/// </summary>
public string Name { get; set; }
/// <summary>
///
/// </summary>
public string Dept { get; set; }
/// <summary>
///
/// </summary>
public string Designation { get; set; }
/// <summary>
///
/// </summary>
public double Experience { get; set; }
//The container for child objects
//private List<IEmployee> subordinateList = new List<IEmployee>();
//Making it public now
/// <summary>
///
/// </summary>
public List<IEmployee> subordinateList = new List<IEmployee>();
/// <summary>
/// To add an employee
/// </summary>
/// <param name="e"></param>
public void AddEmployee(IEmployee e)
{
subordinateList.Add(e);
}
/// <summary>
/// To remove an employee
/// </summary>
/// <param name="e"></param>
public void RemoveEmployee(IEmployee e)
{
subordinateList.Remove(e);
}
/// <summary>
/// Details of a composite node
/// </summary>
public void DisplayDetails()
{
Console.WriteLine($"\n姓名:{Name} 工作在 {Dept} 部门.描述:{Designation}.经历 : {Experience} 年.");
foreach (IEmployee e in subordinateList)
{
e.DisplayDetails();
}
}
public void Accept(IVisitor visitor)
{
visitor.VisitEmployees(this);
}
}
/// <summary>
/// Visitor interface
/// </summary>
interface IVisitor
{
//To visit leaf nodes
void VisitEmployees(Employee employee);
//To visit composite nodes
void VisitEmployees(CompositeEmployee employee);
}
/// <summary>
/// Concrete visitor class-PromotionCheckerVisitor
/// </summary>
class PromotionCheckerVisitor : IVisitor
{
/// <summary>
///
/// </summary>
string eligibleForPromotion = String.Empty;
/// <summary>
/// 工作经历大于15年
/// </summary>
/// <param name="employee"></param>
public void VisitEmployees(CompositeEmployee employee)
{
//We'll promote them if experience is greater than 15 years
eligibleForPromotion = employee.Experience > 15 ? "是" : "否";
Console.WriteLine($"{employee.Name} 来自于 {employee.Dept} 工作长于15年是否有资格升职? :{eligibleForPromotion}");
}
/// <summary>
/// 工作经历在于12年
/// </summary>
/// <param name="employee"></param>
public void VisitEmployees(Employee employee)
{
//We'll promote them if experience is greater than 12 years
eligibleForPromotion = employee.Experience > 12 ? "Yes" : "No";
Console.WriteLine($"{employee.Name} 来自于 {employee.Dept} 工作长于12年是否有资格升职? :{eligibleForPromotion}");
}
}
using DictType = Dictionary<Type, Action<Expression, StringBuilder>>;
/// <summary>
/// 访问者模式 Visitor Pattern
/// geovindu,Geovin Du eidt
/// </summary>
public abstract class Expression
{
}
/// <summary>
///
/// </summary>
public class DoubleExpression : Expression
{
/// <summary>
///
/// </summary>
public double Value;
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public DoubleExpression(double value)
{
Value = value;
}
}
/// <summary>
///
/// </summary>
public class AdditionExpression : Expression
{
/// <summary>
///
/// </summary>
public Expression Left;
/// <summary>
///
/// </summary>
public Expression Right;
/// <summary>
///
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <exception cref="ArgumentNullException"></exception>
public AdditionExpression(Expression left, Expression right)
{
Left = left ?? throw new ArgumentNullException(paramName: nameof(left));
Right = right ?? throw new ArgumentNullException(paramName: nameof(right));
}
}
/// <summary>
///
/// </summary>
public static class ExpressionPrinter
{
/// <summary>
///
/// </summary>
private static DictType actions = new DictType
{
[typeof(DoubleExpression)] = (e, sb) =>
{
var de = (DoubleExpression)e;
sb.Append(de.Value);
},
[typeof(AdditionExpression)] = (e, sb) =>
{
var ae = (AdditionExpression)e;
sb.Append("(");
Print(ae.Left, sb);
sb.Append("+");
Print(ae.Right, sb);
sb.Append(")");
}
};
/// <summary>
///
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public static string Print3(this Expression e)
{
var sb = new StringBuilder();
Print2(e, sb);
return sb.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
/// <param name="sb"></param>
private static void Print2(Expression e, StringBuilder sb)
{
actions[e.GetType()](e, sb);
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
/// <param name="sb"></param>
private static void Print(Expression e, StringBuilder sb)
{
if (e is DoubleExpression de)
{
sb.Append(de.Value);
}
else
if (e is AdditionExpression ae)
{
sb.Append("(");
Print(ae.Left, sb);
sb.Append("+");
Print(ae.Right, sb);
sb.Append(")");
}
// breaks open-closed principle
// will work incorrectly on missing case
}
}
调用:
//访问者模式
Console.WriteLine("***访问者模式 Visitor Pattern with Composite Pattern Demo. ***");
#region Mathematics department
//2 lecturers work in Mathematics department
Employee mathTeacher1 = new Employee { Name = "老大", Dept = "应用数学", Designation = "讲师" ,Experience=13.7};
Employee mathTeacher2 = new Employee { Name = "老二", Dept = "应用数学", Designation = "讲师", Experience = 6.5 };
//The college has a Head of Department in Mathematics
CompositeEmployee hodMaths = new CompositeEmployee { Name = "老三", Dept = "数学", Designation = "数学系主任", Experience = 14 };
//Lecturers of Mathematics directly reports to HOD-Maths
hodMaths.AddEmployee(mathTeacher1);
hodMaths.AddEmployee(mathTeacher2);
#endregion
#region Computer Science department
//3 lecturers work in Computer Sc. department
Employee cseTeacher1 = new Employee { Name = "老四", Dept = "计算机科学", Designation = "讲师", Experience = 10.2 };
Employee cseTeacher2 = new Employee { Name = "老五", Dept = "计算机科学.", Designation = "讲师", Experience = 13.5 };
Employee cseTeacher3 = new Employee { Name = "老六", Dept = "计算机科学", Designation = "讲师", Experience = 7.3 };
//The college has a Head of Department in Computer science
CompositeEmployee hodCompSc = new CompositeEmployee { Name = "老幺", Dept = "计算机科学.", Designation = "计算机科学系主任.", Experience = 16.5 };
//Lecturers of Computer Sc. directly reports to HOD-CSE
hodCompSc.AddEmployee(cseTeacher1);
hodCompSc.AddEmployee(cseTeacher2);
hodCompSc.AddEmployee(cseTeacher3);
#endregion
#region Top level management
//The college also has a Principal
CompositeEmployee principal = new CompositeEmployee { Name = "族长", Dept = "规划监督管理部门", Designation = "校长", Experience = 21 };
//Head of Departments's of Maths and Computer Science directly reports to Principal.
principal.AddEmployee(hodMaths);
principal.AddEmployee(hodCompSc);
#endregion
/*
* Printing the leaf-nodes and branches in the same way.
* i.e. in each case, we are calling DisplayDetails() method.
*/
Console.WriteLine("\nDetails of a college structure is as follows:");
//Prints the complete structure
principal.DisplayDetails();
List<IEmployee> participants = new List<IEmployee>();
//For employees who directly reports to Principal
foreach (IEmployee e in principal.subordinateList)
{
// e.Accept(aVisitor);
participants.Add(e);
}
//For employees who directly reports to HOD-Maths
foreach (IEmployee e in hodMaths.subordinateList)
{
//e.Accept(aVisitor);
participants.Add(e);
}
//For employees who directly reports to HOD-Comp.Sc
foreach (IEmployee e in hodCompSc.subordinateList)
{
//e.Accept(aVisitor);
participants.Add(e);
}
Console.WriteLine("\n***访问者模式 Visitor starts visiting our composite structure***\n");
IVisitor visitor = new PromotionCheckerVisitor();
/*
* Principal is already holding the highest position.
* We are not checking whether he is eligible
* for promotion or not.
*/
//principal.Accept(visitor);
//Visitor is traversing the participant list
foreach ( IEmployee emp in participants)
{
emp.Accept(visitor);
}
//
var geovindu = new AdditionExpression(
left: new DoubleExpression(1),
right: new AdditionExpression(
left: new DoubleExpression(2),
right: new DoubleExpression(3)));
var sb = new StringBuilder();
//ExpressionPrinter.Print2(e, sb);
Console.WriteLine(geovindu.Print3());
输出:
***访问者模式 Visitor Pattern with Composite Pattern Demo. *** Details of a college structure is as follows: 姓名:族长 工作在 规划监督管理部门 部门.描述:校长.经历 : 21 年. 姓名:老三 工作在 数学 部门.描述:数学系主任.经历 : 14 年. 姓名:老大 工作在 应用数学 部门.描述:讲师.经历 : 13.7 年. 姓名:老二 工作在 应用数学 部门.描述:讲师.经历 : 6.5 年. 姓名:老幺 工作在 计算机科学. 部门.描述:计算机科学系主任..经历 : 16.5 年. 姓名:老四 工作在 计算机科学 部门.描述:讲师.经历 : 10.2 年. 姓名:老五 工作在 计算机科学. 部门.描述:讲师.经历 : 13.5 年. 姓名:老六 工作在 计算机科学 部门.描述:讲师.经历 : 7.3 年. ***访问者模式 Visitor starts visiting our composite structure*** 老三 来自于 数学 工作长于15年是否有资格升职? :否 老幺 来自于 计算机科学. 工作长于15年是否有资格升职? :是 老大 来自于 应用数学 工作长于12年是否有资格升职? :Yes 老二 来自于 应用数学 工作长于12年是否有资格升职? :No 老四 来自于 计算机科学 工作长于12年是否有资格升职? :No 老五 来自于 计算机科学. 工作长于12年是否有资格升职? :Yes 老六 来自于 计算机科学 工作长于12年是否有资格升职? :No (1+(2+3))
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号