訪問者模式是一種行爲型設計模式,它允許在不改變被訪問對象結構的前提下,定義對這些對象的新操作。訪問者模式將操作和對象結構分離,使得可以在不修改對象結構的情況下添加新的操作。
訪問者模式有四個主要角色:
-
抽象訪問者(Visitor):定義了訪問者可以訪問的對象的接口,包含了一系列的訪問方法,每個方法對應一種對象的訪問操作。
-
具體訪問者(Concrete Visitor):實現了抽象訪問者接口,對具體的對象結構進行訪問操作。
-
抽象元素(Element):定義了對象結構的公共接口,包含了一個接受訪問者的方法。
-
具體元素(Concrete Element):實現了抽象元素接口,提供了具體的對象結構。
訪問者模式的工作原理如下:
-
抽象訪問者定義了一系列的訪問方法,每個方法對應一種對象的訪問操作。
-
具體訪問者實現了抽象訪問者接口,並實現了對具體對象的訪問操作。
-
抽象元素定義了對象結構的公共接口,幷包含了一個接受訪問者的方法。
-
具體元素實現了抽象元素接口,提供了具體的對象結構,並實現了接受訪問者的方法。
-
客戶端通過調用訪問者的方法,對對象進行訪問操作。
訪問者模式的優點包括:
-
可以對對象結構進行新的操作,而無需修改對象結構本身。
-
可以將相關操作封裝到一個訪問者中,提高了代碼的可維護性和擴展性。
-
可以將對象結構和操作進行解耦,使得代碼更加清晰。
訪問者模式適用於以下場景:
-
當需要對一個複雜對象結構進行一系列不相關或獨立的操作時,可以使用訪問者模式。
-
當對象結構的類層次比較穩定,但經常需要定義新的操作時,可以使用訪問者模式。
總結而言,訪問者模式通過將操作和對象結構分離,可以在不修改對象結構的情況下定義新的操作。它提供了一種靈活的方式來對複雜對象結構進行訪問和操作,並提高了代碼的可維護性和擴展性。
案例:
我們就以養寵物爲例,寵物分別有狗和貓,要給寵物餵食的話,主人可以喂,其他人也可以餵食。
訪問者角色:給寵物餵食的人
具體訪問者角色:主人、其他人
抽象元素角色:動物抽象類
具體元素角色:寵物狗、寵物貓
結構對象角色:主人家
Visitor
public interface IPerson { //優點 定義對象結構的通用功能 void Feed(Cat animal);// 給誰投餵? void Feed(Dog animal);// 給誰投餵? void Feed(Fish animal);// 給誰投餵? //缺點:一是依賴了具體類 ,違反了依賴倒置原則; 二是每增加一個元素(寵物),這裏就要增加一個方法,違反了開閉原則 }
Element
public interface IAnimal { void Accept(IPerson person); }
Concrete Element
public class Cat : IAnimal { public void Accept(IPerson person) { person.Feed(this); Console.WriteLine("好喫,喵喵喵"); } }
public class Dog : IAnimal { public void Accept(IPerson person) { person.Feed(this); Console.WriteLine("我喫飽了,汪汪汪..."); } }
public class Fish : IAnimal { public void Accept(IPerson person) { person.Feed(this); Console.WriteLine("咕嚕嚕....."); } }
Concrete Visitor
public class Master : IPerson { public void Feed(Cat animal) { Console.WriteLine("主人自已喂貓"); } public void Feed(Dog animal) { Console.WriteLine("主人自已餵狗"); } public void Feed(Fish animal) { Console.WriteLine("主人自已餵魚"); } }
public class Friend : IPerson { public void Feed(Cat animal) { Console.WriteLine("好朋友幫主人喂貓"); } public void Feed(Dog animal) { Console.WriteLine("好朋友幫主人餵狗"); } public void Feed(Fish animal) { Console.WriteLine("好朋友幫主人餵魚"); } }
Object Structure
/// <summary> /// 結構對象角色 /// </summary> public class Home { private readonly List<IAnimal> animals = new List<IAnimal>(); public void Add(IAnimal animal) { animals.Add(animal); } public void Start(IPerson person) { foreach (var animal in animals) { animal.Accept(person); } } }
調用
internal class Client { public void Start() { Home home = new Home(); home.Add(new Dog()); home.Add(new Cat()); Master master=new Master(); home.Start(master); home.Add(new Fish()); Friend friend=new Friend(); home.Start(friend); } }
static void Main(string[] args) { new Client().Start(); Console.ReadKey(); }