程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 《模式——工程化實現及擴展》訪問者模式 Visitor—“自我檢驗 參考答案

《模式——工程化實現及擴展》訪問者模式 Visitor—“自我檢驗 參考答案

編輯:C#入門知識

下面我們把本章正文部分的HR系統示例進一步復雜化:

1、 系統管理的人員類型包括三大類4小類:

a.       員工(Employee):包括普通員工(General Employee),經理(Manager)

b.      臨時員工(Temporary)

c.       外聘專家(Expert)

2、 管理的內容包括三大類8小類,而且預期還會不斷增加

a.       薪金:包括底薪、司齡工資(與在公司工作年限相關)、不定期的崗位加薪和外聘專家的聘金

b.      保險和公積金:養老保險和住房公積金

c.       假期:年休假、崗位增休假

3、 現有功能需求

a.       薪金:

                                                               i.      司齡工資:每年增加50元

                                                             ii.      不定期的崗位加薪:計劃給普通員工和經理分別加薪15%和10%

b.      保險和公積金:為了簡化示例,養老保險和住房公積金分別按最後應發收入合計的5%和15%扣除

c.       假期:

                                                               i.      年休假:所有員工(普通員工、經理)按照司齡從每年5天起,每滿5年年度增加5天逐級遞增

                                                             ii.      崗位增休假:計劃在現有休假基礎上,普通員工每年增加3天,經理每年增加5天

請采用本章介紹的任意一種訪問者模式實現方式(“經典方式”、“Dynamic方式”和“LINQ + 委托方式”),完成上述功能,並通過單元測試驗證。

 

       要求:

1、 依賴關系盡可能簡潔

2、 實現方式盡可能簡潔、實用

3、 便於從“人員類型”和“管理內容”兩方面擴展

分析

1、由於需要同時從管理內容和人員類型兩方面進行調整,所有需要借助.NET平台解耦雙因素依賴關系


2、為了實現簡便采用LINQ + 委托方式

3、為了便於隨著應用項目維護進行修改,將所有人員類型和管理內容以配置方式動態載入

4、為了簡化眾多內容,提供統一的Facade接口,協調眾多人員類型和管理內容間的行為匹配

 

 

參考實現

 1、人員類型定義

#region Staff

abstract class Person
{
    public string Name { get; set; }
    public virtual double Income { get; set;}
    public virtual object Clone() {return MemberwiseClone();}
}

/// <summary>
/// 外聘專家
/// </summary>
class Expert : Person
{
    public Expert(double cost)
    {
        Cost = cost;
        Income = Cost;
    }
    public double Cost { get; set; }
}

abstract class Employee : Person { }

class GeneralEmployee : Employee
{
    public GeneralEmployee(double basicSalary, int workingYears)
    {
        BasicSalary = basicSalary;
        WorkingYears = workingYears;
    }
    public double BasicSalary { get; set; }
    public double ExtraSalary { get; set; }
    public int WorkingYears { get; set; }
    public int VacationDays { get; set; }

    public override double Income{get{return BasicSalary + ExtraSalary;}}
}

class Temporary : Employee
{
    public double Wage { get; set; }
    public override double Income{get{return Wage;}}
}

class Mananger : GeneralEmployee
{
    public Mananger(double basicSalary, int workingYears, string department)
        : base(basicSalary, workingYears)
    {
        Department = department;
    }
    public string Department { get; private set; }
}

#endregion
 

 2、訪問接口和訪問過程定義

class HrRuntime
{
    /// <summary>
    /// 所有Element接受Visitor的統一入口
    /// </summary>
    /// <remarks>
    ///     Type    表示適用的人員類別
    ///     Action  表示Visitor擴展的功能
    /// </remarks>
    public IEnumerable<KeyValuePair<Type, Action<Person>>> Registry { get; set; }

    /// <summary>
    /// 所有Element
    /// </summary>
    public List<Person> Staff { get; set; }

    /// <summary>
    /// 調用各個適用的Visitor
    /// </summary>
    public void Visit()
    {
        if(Registry.Count() == 0) return;
        if(Staff.Count() == 0) return;

        //  動態生成傳統Visit各個接口的過程
        //      VisitGeneralExpert()
        //      VisitGeneralTemporary()
        //      VisitGeneralGeneralEmployee()
        //      VisitGeneralManager()
        var visitorsByType = Registry.GroupBy(x => x.Key);

        //  動態執行Visit()過程
        Staff.ForEach(x => Registry.Where(a => a.Key == x.GetType()).ToList().ForEach(a => a.Value(x)));
    }

    public T FindClone<T>(string name)
        where T : Person
    {
        return (T)(Staff.FirstOrDefault(x=>string.Equals(x.Name, name)).Clone());
    }
}
 

3、單元測試驗證各種管理措施與各類人員間的訪問效果

 

HrRuntime runtime;
const double MaxMistake = 0.1;

[TestInitialize]

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved