日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

北风设计模式课程---访问者模式(Visitor)

發(fā)布時(shí)間:2023/12/20 asp.net 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 北风设计模式课程---访问者模式(Visitor) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

北風(fēng)設(shè)計(jì)模式課程---訪問(wèn)者模式(Visitor)

一、總結(jié)

一句話總結(jié):

設(shè)計(jì)模式是日常問(wèn)題的經(jīng)驗(yàn)總結(jié)方案,所以學(xué)好設(shè)計(jì)模式對(duì)日常出現(xiàn)的問(wèn)題可以有很好的解決。
訪問(wèn)者設(shè)計(jì)模式有點(diǎn)神似 抽象工廠模式,都是增加一個(gè)維度很容易,增加另外一個(gè)維度很麻煩

?

1、訪問(wèn)者模式實(shí)例?

1、在患者就醫(yī)時(shí),醫(yī)生會(huì)根據(jù)病情開(kāi)具處方單,很多醫(yī)院都會(huì)存在以下這個(gè)流程:劃價(jià)人員拿到處方單之后根據(jù)藥品名稱和數(shù)量計(jì)算總價(jià),而藥房工作人員根據(jù)藥品名稱和數(shù)量準(zhǔn)備藥品,
2、在軟件開(kāi)發(fā)中,有時(shí)候也需要處理像處方單這樣的集合對(duì)象結(jié)構(gòu),在該對(duì)象結(jié)構(gòu)中存儲(chǔ)了多個(gè)不同類型的對(duì)象信息,而且對(duì)同一對(duì)象結(jié)構(gòu)中的元素的操作方式并不唯一,可能需要提供多種不同的處理方式。在設(shè)計(jì)模式中,有一種模式可以滿足上述要求,其模式動(dòng)機(jī)就是以不同的方式操作復(fù)雜對(duì)象結(jié)構(gòu),該模式就是訪問(wèn)者模式。

?

2、訪問(wèn)者模式簡(jiǎn)介?

1、訪問(wèn)者模式是一種較為復(fù)雜的行為型模式,它包含【訪問(wèn)者和被訪問(wèn)元素】?jī)蓚€(gè)主要組成部分,這些被訪問(wèn)的元素通常具有不同的類型,且【不同的訪問(wèn)者可以對(duì)它們進(jìn)行不同的訪問(wèn)操作】。例如:【處方單中的各種藥品信息就是被訪問(wèn)的元素,而劃價(jià)人員和藥房工作人員就是訪問(wèn)者】。訪問(wèn)者模式可以使得用戶在不修改現(xiàn)有系統(tǒng)的情況下擴(kuò)展系統(tǒng)的功能,為這些不同類型的元素增加新的操作。
2、提供一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作表示,它使得可以在不改變各元素的類的前提下定義作用于這些元素的新操作。

?

?

3、訪問(wèn)者模式主要角色?

1、Visitor(抽象訪問(wèn)者)/ConcreteVisitor(具體訪問(wèn)者):抽象訪問(wèn)者為對(duì)象結(jié)構(gòu)中每一個(gè)具體元素類ConcreteElement聲明一個(gè)訪問(wèn)操作,從這個(gè)操作的名稱或參數(shù)類型可以清楚知道需要訪問(wèn)的具體元素的類型,具體訪問(wèn)者則需要實(shí)現(xiàn)這些操作方法,定義對(duì)這些元素的訪問(wèn)操作。具體訪問(wèn)者實(shí)現(xiàn)了抽象訪問(wèn)者聲明的方法,每一個(gè)操作作用于訪問(wèn)對(duì)象結(jié)構(gòu)中一種類型的元素。
2、Element(抽象元素)/ConcreteElement(具體元素):一般是一個(gè)抽象類或接口,定義一個(gè)Accept方法,該方法通常以一個(gè)抽象訪問(wèn)者作為參數(shù)。具體元素實(shí)現(xiàn)了Accept方法,在Accept方法中調(diào)用訪問(wèn)者的訪問(wèn)方法以便完成一個(gè)元素的操作。
3、ObjectStructure(對(duì)象結(jié)構(gòu)):對(duì)象結(jié)構(gòu)是一個(gè)元素的集合,用于存放元素對(duì)象,且提供便利其內(nèi)部元素的方法。


  (1)Visitor(抽象訪問(wèn)者):抽象訪問(wèn)者為對(duì)象結(jié)構(gòu)中每一個(gè)具體元素類ConcreteElement聲明一個(gè)訪問(wèn)操作,從這個(gè)操作的名稱或參數(shù)類型可以清楚知道需要訪問(wèn)的具體元素的類型,具體訪問(wèn)者則需要實(shí)現(xiàn)這些操作方法,定義對(duì)這些元素的訪問(wèn)操作。
  (2)ConcreteVisitor(具體訪問(wèn)者):具體訪問(wèn)者實(shí)現(xiàn)了抽象訪問(wèn)者聲明的方法,每一個(gè)操作作用于訪問(wèn)對(duì)象結(jié)構(gòu)中一種類型的元素。
  (3)Element(抽象元素):一般是一個(gè)抽象類或接口,定義一個(gè)Accept方法,該方法通常以一個(gè)抽象訪問(wèn)者作為參數(shù)。
  (4)ConcreteElement(具體元素):具體元素實(shí)現(xiàn)了Accept方法,在Accept方法中調(diào)用訪問(wèn)者的訪問(wèn)方法以便完成一個(gè)元素的操作。
  (5)ObjectStructure(對(duì)象結(jié)構(gòu)):對(duì)象結(jié)構(gòu)是一個(gè)元素的集合,用于存放元素對(duì)象,且提供便利其內(nèi)部元素的方法。

?

4、訪問(wèn)者模式 實(shí)現(xiàn) 重構(gòu)OA系統(tǒng)員工數(shù)據(jù) 的角色實(shí)例?

1、FinanceDepartment表示財(cái)務(wù)部,HRDepartment表示人力資源部,它們充當(dāng)具體訪問(wèn)者的角色,其抽象父類Department充當(dāng)抽象訪問(wèn)者角色;
2、EmployeeList充當(dāng)對(duì)象結(jié)構(gòu),用于存儲(chǔ)員工列表;
3、FullTimeEmployee表示全職員工,PartTimeEmployee表示兼職員工,它們充當(dāng)具體元素角色,而其父類IEmployee(這里實(shí)現(xiàn)形式是interface)充當(dāng)抽象元素角色。

?

5、訪問(wèn)者模式中的對(duì)象結(jié)構(gòu)類示例?

|||-begin

/// <summary>/// 對(duì)象結(jié)構(gòu)類:EmployeeList/// </summary>public class EmployeeList{private IList<IEmployee> empList = new List<IEmployee>();public void AddEmployee(IEmployee emp){this.empList.Add(emp);}public void Accept(Department handler){foreach (var emp in empList){emp.Accept(handler);}}

|||-end

private IList<IEmployee> empList = new List<IEmployee>();:用于存儲(chǔ)員工列表

?

6、訪問(wèn)模式的主要優(yōu)缺點(diǎn)?

1、增加新的訪問(wèn)操作十分方便,不痛不癢 => 符合開(kāi)閉原則
2、增加新的元素類很困難,需要在每一個(gè)訪問(wèn)者類中增加相應(yīng)訪問(wèn)操作代碼 => 違背了開(kāi)閉原則

?

7、適合多維的設(shè)計(jì)模式?

訪問(wèn)者設(shè)計(jì)模式,抽象工廠設(shè)計(jì)模式,橋接模式,外觀模式

?

8、訪問(wèn)者模式 主要優(yōu)點(diǎn)?

(1)增加新的訪問(wèn)操作十分方便,不痛不癢 => 符合開(kāi)閉原則
(2)將有關(guān)元素對(duì)象的訪問(wèn)行為集中到一個(gè)訪問(wèn)者對(duì)象中,而不是分散在一個(gè)個(gè)的元素類中,類的職責(zé)更加清晰 => 符合單一職責(zé)原則

?

9、訪問(wèn)者模式 主要缺點(diǎn)?

(1)增加新的元素類很困難,需要在每一個(gè)訪問(wèn)者類中增加相應(yīng)訪問(wèn)操作代碼 => 違背了開(kāi)閉原則
(2)元素對(duì)象有時(shí)候必須暴露一些自己的內(nèi)部操作和狀態(tài),否則無(wú)法供訪問(wèn)者訪問(wèn) => 破壞了元素的封裝性

?

10、訪問(wèn)者模式 應(yīng)用場(chǎng)景?

(1)一個(gè)對(duì)象結(jié)構(gòu)包含多個(gè)類型的對(duì)象,希望對(duì)這些對(duì)象實(shí)施一些依賴其具體類型的操作。=> 不同的類型可以有不同的訪問(wèn)操作
(2)對(duì)象結(jié)構(gòu)中對(duì)象對(duì)應(yīng)的類很少改變 很少改變 很少改變(重要的事情說(shuō)三遍),但經(jīng)常需要在此對(duì)象結(jié)構(gòu)上定義新的操作。

?

11、訪問(wèn)者模式實(shí)例?

- M公司開(kāi)發(fā)部想要為某企業(yè)開(kāi)發(fā)一個(gè)OA系統(tǒng),在該OA系統(tǒng)中包含一個(gè)員工信息管理子系統(tǒng),該企業(yè)包括正式員工和臨時(shí)工,每周HR部門和財(cái)務(wù)部等部門需要對(duì)員工數(shù)據(jù)進(jìn)行匯總,匯總數(shù)據(jù)包括員工工作時(shí)間、員工工資等等。該企業(yè)的基本制度如下:
- (1)正式員工(Full time Employee)每周工作時(shí)間為40小時(shí),不同級(jí)別、不同部門的員工每周基本工資不同;如果超過(guò)40小時(shí),超出部分按照100元/小時(shí)作為加班費(fèi);如果少于40小時(shí),所缺時(shí)間按照請(qǐng)假處理,請(qǐng)假鎖扣工資以80元/小時(shí)計(jì)算,直到基本工資扣除到0為止。除了記錄實(shí)際工作時(shí)間外,HR部需要記錄加班時(shí)長(zhǎng)或請(qǐng)假時(shí)長(zhǎng),作為員工平時(shí)表現(xiàn)的一項(xiàng)依據(jù)。
- (2)臨時(shí)員工(Part time Employee)每周工作時(shí)間不固定,基本工資按照小時(shí)計(jì)算,不同崗位的臨時(shí)工小時(shí)工資不同。HR部只需要記錄實(shí)際工作時(shí)間。
- HR人力資源部和財(cái)務(wù)部工作人員可以根據(jù)各自的需要對(duì)員工數(shù)據(jù)進(jìn)行匯總處理,HR人力資源部負(fù)責(zé)匯總每周員工工作時(shí)間,而財(cái)務(wù)部負(fù)責(zé)計(jì)算每周員工工資。

?

?

二、設(shè)計(jì)模式的征途—16.訪問(wèn)者(Visitor)模式

轉(zhuǎn)自或參考:設(shè)計(jì)模式的征途—16.訪問(wèn)者(Visitor)模式
https://www.cnblogs.com/edisonchou/p/7247990.html

在患者就醫(yī)時(shí),醫(yī)生會(huì)根據(jù)病情開(kāi)具處方單,很多醫(yī)院都會(huì)存在以下這個(gè)流程:劃價(jià)人員拿到處方單之后根據(jù)藥品名稱和數(shù)量計(jì)算總價(jià),而藥房工作人員根據(jù)藥品名稱和數(shù)量準(zhǔn)備藥品,如下圖所示。

在軟件開(kāi)發(fā)中,有時(shí)候也需要處理像處方單這樣的集合對(duì)象結(jié)構(gòu),在該對(duì)象結(jié)構(gòu)中存儲(chǔ)了多個(gè)不同類型的對(duì)象信息,而且對(duì)同一對(duì)象結(jié)構(gòu)中的元素的操作方式并不唯一,可能需要提供多種不同的處理方式。在設(shè)計(jì)模式中,有一種模式可以滿足上述要求,其模式動(dòng)機(jī)就是以不同的方式操作復(fù)雜對(duì)象結(jié)構(gòu),該模式就是訪問(wèn)者模式。

訪問(wèn)者模式(Visitor)學(xué)習(xí)難度:★★★★☆使用頻率:★☆☆☆☆

一、OA系統(tǒng)員工數(shù)據(jù)匯總設(shè)計(jì)

1.1 需求背景

Background:M公司開(kāi)發(fā)部想要為某企業(yè)開(kāi)發(fā)一個(gè)OA系統(tǒng),在該OA系統(tǒng)中包含一個(gè)員工信息管理子系統(tǒng),該企業(yè)包括正式員工和臨時(shí)工,每周HR部門和財(cái)務(wù)部等部門需要對(duì)員工數(shù)據(jù)進(jìn)行匯總,匯總數(shù)據(jù)包括員工工作時(shí)間、員工工資等等。該企業(yè)的基本制度如下:

(1)正式員工(Full time Employee)每周工作時(shí)間為40小時(shí),不同級(jí)別、不同部門的員工每周基本工資不同;如果超過(guò)40小時(shí),超出部分按照100元/小時(shí)作為加班費(fèi);如果少于40小時(shí),所缺時(shí)間按照請(qǐng)假處理,請(qǐng)假鎖扣工資以80元/小時(shí)計(jì)算,直到基本工資扣除到0為止。除了記錄實(shí)際工作時(shí)間外,HR部需要記錄加班時(shí)長(zhǎng)或請(qǐng)假時(shí)長(zhǎng),作為員工平時(shí)表現(xiàn)的一項(xiàng)依據(jù)。

(2)臨時(shí)員工(Part time Employee)每周工作時(shí)間不固定,基本工資按照小時(shí)計(jì)算,不同崗位的臨時(shí)工小時(shí)工資不同。HR部只需要記錄實(shí)際工作時(shí)間。

HR人力資源部和財(cái)務(wù)部工作人員可以根據(jù)各自的需要對(duì)員工數(shù)據(jù)進(jìn)行匯總處理,HR人力資源部負(fù)責(zé)匯總每周員工工作時(shí)間,而財(cái)務(wù)部負(fù)責(zé)計(jì)算每周員工工資。

1.2 初始設(shè)計(jì)

  M公司開(kāi)發(fā)人員針對(duì)需求,提出了一個(gè)初始的解決方案,其核心代碼如下:

public class EmployeeList{// 員工集合private IList<Employee> empList = new List<Employee>();// 增加員工public void AddEmployee(Employee emp){this.empList.Add(emp);}// 處理員工數(shù)據(jù)public void Handle(string deptName){if (deptName.Equals("財(cái)務(wù)部")){foreach (var emp in empList){if (emp.GetType().Equals("FullTimeEmployee")){Console.WriteLine("財(cái)務(wù)部處理全職員工數(shù)據(jù)!");}else{Console.WriteLine("財(cái)務(wù)部處理兼職員工數(shù)據(jù)!");}}}else if (deptName.Equals("人力資源部")){foreach (var emp in empList){if (emp.GetType().Equals("FullTimeEmployee")){Console.WriteLine("人力資源部處理全職員工數(shù)據(jù)!");}else{Console.WriteLine("人力資源部處理兼職員工數(shù)據(jù)!");}}}}}

  不難發(fā)現(xiàn),該解決方案存在以下問(wèn)題:

  (1)EmployeeList類非常龐大,承擔(dān)了過(guò)多的職責(zé),既不便于代碼復(fù)用,也不便于系統(tǒng)擴(kuò)展,違背了單一職責(zé)原則。

  (2)包含了大量的if-else語(yǔ)句,測(cè)試和維護(hù)的難度增大。

  (3)如果要新增一個(gè)部門來(lái)操作員工數(shù)據(jù)集合,那么不得不修改EmployeeList類的源代碼,違背了開(kāi)閉原則。

  訪問(wèn)者模式是一個(gè)可以考慮用來(lái)解決的方案,它可以在一定程度上解決上述問(wèn)題(大部分問(wèn)題)。

二、訪問(wèn)者模式概述

2.1 訪問(wèn)者模式簡(jiǎn)介

  訪問(wèn)者模式是一種較為復(fù)雜的行為型模式,它包含訪問(wèn)者和被訪問(wèn)元素兩個(gè)主要組成部分,這些被訪問(wèn)的元素通常具有不同的類型,且不同的訪問(wèn)者可以對(duì)它們進(jìn)行不同的訪問(wèn)操作。例如:處方單中的各種藥品信息就是被訪問(wèn)的元素,而劃價(jià)人員和藥房工作人員就是訪問(wèn)者。訪問(wèn)者模式可以使得用戶在不修改現(xiàn)有系統(tǒng)的情況下擴(kuò)展系統(tǒng)的功能,為這些不同類型的元素增加新的操作。

訪問(wèn)者(Visitor)模式:提供一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作表示,它使得可以在不改變各元素的類的前提下定義作用于這些元素的新操作。訪問(wèn)者模式是一種對(duì)象行為型模式。

2.2 訪問(wèn)者模式結(jié)構(gòu)

  訪問(wèn)者模式結(jié)構(gòu)圖中包含以下5個(gè)角色:

  (1)Visitor(抽象訪問(wèn)者):抽象訪問(wèn)者為對(duì)象結(jié)構(gòu)中每一個(gè)具體元素類ConcreteElement聲明一個(gè)訪問(wèn)操作,從這個(gè)操作的名稱或參數(shù)類型可以清楚知道需要訪問(wèn)的具體元素的類型,具體訪問(wèn)者則需要實(shí)現(xiàn)這些操作方法,定義對(duì)這些元素的訪問(wèn)操作。

  (2)ConcreteVisitor(具體訪問(wèn)者):具體訪問(wèn)者實(shí)現(xiàn)了抽象訪問(wèn)者聲明的方法,每一個(gè)操作作用于訪問(wèn)對(duì)象結(jié)構(gòu)中一種類型的元素。

  (3)Element(抽象元素):一般是一個(gè)抽象類或接口,定義一個(gè)Accept方法,該方法通常以一個(gè)抽象訪問(wèn)者作為參數(shù)。

  (4)ConcreteElement(具體元素):具體元素實(shí)現(xiàn)了Accept方法,在Accept方法中調(diào)用訪問(wèn)者的訪問(wèn)方法以便完成一個(gè)元素的操作。

  (4)ObjectStructure(對(duì)象結(jié)構(gòu)):對(duì)象結(jié)構(gòu)是一個(gè)元素的集合,用于存放元素對(duì)象,且提供便利其內(nèi)部元素的方法。

三、重構(gòu)OA系統(tǒng)員工數(shù)據(jù)匯總

3.1 重構(gòu)后的設(shè)計(jì)結(jié)構(gòu)

  在上圖中,FinanceDepartment表示財(cái)務(wù)部,HRDepartment表示人力資源部,它們充當(dāng)具體訪問(wèn)者的角色,其抽象父類Department充當(dāng)抽象訪問(wèn)者角色;EmployeeList充當(dāng)對(duì)象結(jié)構(gòu),用于存儲(chǔ)員工列表;FullTimeEmployee表示全職員工,PartTimeEmployee表示兼職員工,它們充當(dāng)具體元素角色,而其父類IEmployee(這里實(shí)現(xiàn)形式是interface)充當(dāng)抽象元素角色。

3.2 具體代碼實(shí)現(xiàn)

  (1)抽象元素=>IEmployee

/// <summary>/// 抽象元素類:Employee/// </summary>public interface IEmployee{void Accept(Department handler);}

  (2)具體元素=>FullTimeEmployee,PartTimeEmployee

/// <summary>/// 具體元素類:FullTimeEmployee/// </summary>public class FullTimeEmployee : IEmployee{public string Name { get; set; }public double WeeklyWage { get; set; }public int WorkTime { get; set; }public FullTimeEmployee(string name, double weeklyWage, int workTime){this.Name = name;this.WeeklyWage = weeklyWage;this.WorkTime = workTime;}public void Accept(Department handler){handler.Visit(this);}}/// <summary>/// 具體元素類:PartTimeEmployee/// </summary>public class PartTimeEmployee : IEmployee{public string Name { get; set; }public double HourWage { get; set; }public int WorkTime { get; set; }public PartTimeEmployee(string name, double hourWage, int workTime){this.Name = name;this.HourWage = hourWage;this.WorkTime = workTime;}public void Accept(Department handler){handler.Visit(this);}}

  (3)對(duì)象結(jié)構(gòu)=>EmployeeList

/// <summary>/// 對(duì)象結(jié)構(gòu)類:EmployeeList/// </summary>public class EmployeeList{private IList<IEmployee> empList = new List<IEmployee>();public void AddEmployee(IEmployee emp){this.empList.Add(emp);}public void Accept(Department handler){foreach (var emp in empList){emp.Accept(handler);}}

  (4)抽象訪問(wèn)者=>Department

/// <summary>/// 抽象訪問(wèn)者類:Department/// </summary>public abstract class Department{// 聲明一組重載的訪問(wèn)方法,用于訪問(wèn)不同類型的具體元素public abstract void Visit(FullTimeEmployee employee);public abstract void Visit(PartTimeEmployee employee);}

  (5)具體訪問(wèn)者=>FinanceDepartment,HRDepartment

/// <summary>/// 具體訪問(wèn)者類:FinanceDepartment/// </summary>public class FinanceDepartment : Department{// 實(shí)現(xiàn)財(cái)務(wù)部對(duì)兼職員工數(shù)據(jù)的訪問(wèn)public override void Visit(PartTimeEmployee employee){int workTime = employee.WorkTime;double hourWage = employee.HourWage;Console.WriteLine("臨時(shí)工 {0} 實(shí)際工資為:{1} 元", employee.Name, workTime * hourWage);}// 實(shí)現(xiàn)財(cái)務(wù)部對(duì)全職員工數(shù)據(jù)的訪問(wèn)public override void Visit(FullTimeEmployee employee){int workTime = employee.WorkTime;double weekWage = employee.WeeklyWage;if (workTime > 40){weekWage = weekWage + (workTime - 40) * 50;}else if (workTime < 40){weekWage = weekWage - (40 - workTime) * 80;if (weekWage < 0){weekWage = 0;}}Console.WriteLine("正式員工 {0} 實(shí)際工資為:{1} 元", employee.Name, weekWage);}}/// <summary>/// 具體訪問(wèn)者類:HRDepartment/// </summary>public class HRDepartment : Department{// 實(shí)現(xiàn)人力資源部對(duì)兼職員工數(shù)據(jù)的訪問(wèn)public override void Visit(PartTimeEmployee employee){int workTime = employee.WorkTime;Console.WriteLine("臨時(shí)工 {0} 實(shí)際工作時(shí)間為:{1} 小時(shí)", employee.Name, workTime);}// 實(shí)現(xiàn)人力資源部對(duì)全職員工數(shù)據(jù)的訪問(wèn)public override void Visit(FullTimeEmployee employee){int workTime = employee.WorkTime;Console.WriteLine("正式員工 {0} 實(shí)際工作時(shí)間為:{1} 小時(shí)", employee.Name, workTime);if (workTime > 40){Console.WriteLine("正式員工 {0} 加班時(shí)間為:{1} 小時(shí)", employee.Name, workTime - 40);}else if (workTime < 40){Console.WriteLine("正式員工 {0} 請(qǐng)假時(shí)間為:{1} 小時(shí)", employee.Name, 40 - workTime);}}}

  (6)客戶端調(diào)用與測(cè)試

public class Program{public static void Main(string[] args){EmployeeList empList = new EmployeeList();IEmployee fteA = new FullTimeEmployee("梁思成", 3200.00, 45);IEmployee fteB = new FullTimeEmployee("徐志摩", 2000, 40);IEmployee fteC = new FullTimeEmployee("梁徽因", 2400, 38);IEmployee fteD = new PartTimeEmployee("方鴻漸", 80, 20);IEmployee fteE = new PartTimeEmployee("唐宛如", 60, 18);empList.AddEmployee(fteA);empList.AddEmployee(fteB);empList.AddEmployee(fteC);empList.AddEmployee(fteD);empList.AddEmployee(fteE);Department dept = AppConfigHelper.GetDeptInstance() as Department;if (dept != null){empList.Accept(dept);}Console.ReadKey();}}

  其中,AppConfigHelper用于從配置文件中獲得具體訪問(wèn)者實(shí)例,配置文件如下:

<?xml version="1.0" encoding="utf-8" ?> <configuration><appSettings><add key="DeptName" value="Manulife.ChengDu.DesignPattern.Visitor.HRDepartment, Manulife.ChengDu.DesignPattern.Visitor" /></appSettings> </configuration>

  AppConfigHelper的具體代碼如下:

public class AppConfigHelper{public static string GetDeptName(){string factoryName = null;try{factoryName = System.Configuration.ConfigurationManager.AppSettings["DeptName"];}catch (Exception ex){Console.WriteLine(ex.Message);}return factoryName;}public static object GetDeptInstance(){string assemblyName = AppConfigHelper.GetDeptName();Type type = Type.GetType(assemblyName);var instance = Activator.CreateInstance(type);return instance;}} View Code

  編譯運(yùn)行后的結(jié)果如下:

  

  如果需要更換具體訪問(wèn)者類,無(wú)須修改源代碼,只需要修改一下配置文件。例如這里將訪問(wèn)者由人力資源部更改為財(cái)務(wù)部:

<?xml version="1.0" encoding="utf-8" ?> <configuration><appSettings><add key="DeptName" value="Manulife.ChengDu.DesignPattern.Visitor.FinanceDepartment, Manulife.ChengDu.DesignPattern.Visitor" /></appSettings> </configuration>

?  此時(shí)再次運(yùn)行則會(huì)得到以下結(jié)果:

  

  可以看出,如果我們要在系統(tǒng)中新增訪問(wèn)者,那么無(wú)需修改源代碼,只需新增一個(gè)新的具體訪問(wèn)者類即可,從這一點(diǎn)看,訪問(wèn)者模式符合開(kāi)閉原則。

  但是,如果我們要在系統(tǒng)中新增具體元素,比如新增一個(gè)新的員工類型為“退休人員”,由于原系統(tǒng)并未提供相應(yīng)的訪問(wèn)接口,因此必須對(duì)原有系統(tǒng)進(jìn)行修改。所以,從新增新的元素來(lái)看,訪問(wèn)者模式違背了開(kāi)閉原則

  因此,訪問(wèn)者模式與抽象工廠模式類似,對(duì)于開(kāi)閉原則的支持具有“傾斜”性,可以方便地新增訪問(wèn)者,但是添加新的元素較為麻煩。

四、訪問(wèn)者模式總結(jié)

4.1 主要優(yōu)點(diǎn)

  (1)增加新的訪問(wèn)操作十分方便,不痛不癢 => 符合開(kāi)閉原則

  (2)將有關(guān)元素對(duì)象的訪問(wèn)行為集中到一個(gè)訪問(wèn)者對(duì)象中,而不是分散在一個(gè)個(gè)的元素類中,類的職責(zé)更加清晰 =>?符合單一職責(zé)原則

4.2 主要缺點(diǎn)

  (1)增加新的元素類很困難,需要在每一個(gè)訪問(wèn)者類中增加相應(yīng)訪問(wèn)操作代碼 => 違背了開(kāi)閉原則

  (2)元素對(duì)象有時(shí)候必須暴露一些自己的內(nèi)部操作和狀態(tài),否則無(wú)法供訪問(wèn)者訪問(wèn) => 破壞了元素的封裝性

4.3?應(yīng)用場(chǎng)景

  (1)一個(gè)對(duì)象結(jié)構(gòu)包含多個(gè)類型的對(duì)象,希望對(duì)這些對(duì)象實(shí)施一些依賴其具體類型的操作。=> 不同的類型可以有不同的訪問(wèn)操作

  (2)對(duì)象結(jié)構(gòu)中對(duì)象對(duì)應(yīng)的類很少改變?很少改變 很少改變(重要的事情說(shuō)三遍),但經(jīng)常需要在此對(duì)象結(jié)構(gòu)上定義新的操作。

參考資料

  

  劉偉,《設(shè)計(jì)模式的藝術(shù)—軟件開(kāi)發(fā)人員內(nèi)功修煉之道》

?

轉(zhuǎn)載于:https://www.cnblogs.com/Renyi-Fan/p/11105295.html

總結(jié)

以上是生活随笔為你收集整理的北风设计模式课程---访问者模式(Visitor)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。