並做不同的動作處理,將把這處理器(Visitor)的部份獨立出來成為物件
也就是將資料處理由資料結構中分離出來,就是Visitor Pattern。
例如,有一個檔案架構系統,希望把整個檔案目錄架構整個列印出來,
需要有一個print_Visitor是負責來做把檔案列印出來的工作,
只要把這print_Visitor丟到一個複雜架構(acceptor)內,就會達到這目的。
如果在這檔案架構內,希望可以把所有圖檔都可以產生一個縮圖
這時候,可以產生另一個thumb_Visitor,用來負責產生縮圖的工作
只要把這thumb_Visitor丟到架構內,就會達到目的。
對於一個複雜架構的系統(Acceptor),丟進去不同功能的Visitor
就可以對整個系統做不同功能的事。
實作Visitor Pattern會用到一個比較複雜的遞迴(Double dispatch)
一般遞迴是自己呼叫自己,在這裡面是Acceptor與Visitor的彼此呼叫遞迴
參與者
1.Acceptor - 內需要定義一個accept method,這method只是都固定用來把自己當作參數,呼叫啟動visitor的巡訪動作:
public Class Acceptor {
public void accept(Visitor v){
v.visit(this)
};
.....
}
2.Visitor - 程式的運作核心是在Visitor的visit function:
public Class Visitor{
public void visit(Acceptor entry){
Iterator it=entry.iterator()
while(it.hasNext()){
Acceptor en=it.next();
en.accept(this);
}
}
}
3.Main - 外部程式
Acceptor rootdir=new Acceptor("root");
rootdir.accept(new Visitor());
4.在Visitor實作迴圈上
private String currentdir=""
public void visit(Directory dir){
String savedir=currentdir+"/"+dir.getName()
Iterator it=dir.iterator();
while(it.hasNext()){
Entry entry=(Entry)it.next();
entry.accept(this)
}
currentdir=savedir;
}
下面操作表示可以在物體結構的元素進行。訪客可以讓你定義一個新的操作,而不改變其運作上的元素的類。
進階的運用,和角色類和參與這個模式的對象可以更細分如下:
Visitor (Visitor)
聲明在對象結構中的每個類ConcreteElement的訪問操作。操作的名稱和簽名識別發送訪問請求,訪問者的類。讓參觀者確定具體類的元素被訪問。那麼Visitor可以通過其特定的界面直接訪問的元素.。
ConcreteVisitor(IncomeVisitor,VacationVisitor)
實現由觀眾宣布每個操作。每個操作實現為在結構中相應的類或對象中定義的算法的一個片段。 ConcreteVisitor提供了上下文的算法和存儲其本地狀態。這種狀態經常結構的遍歷期間累積的結果。
Element (Element)
定義一個接受的操作,需要一個Visitor作為一個參數。
ConcreteElement (Employee)
實現了一個接受的操作,需要一個Visitor作為一個參數.
ObjectStructure (Employees)
可以枚舉它的元素
可提供一個高層次的接口,以允許訪問者訪問其元素
可以是一個複合物(圖案)或集合,例如一個清單或一組
這種結構的代碼演示在其中一個對象遍歷對象結構,在這種結構中的每個節點上執行相同的操作的訪問者模式。不同的Visitor對象定義不同的操作。
using System;
using System.Collections.Generic;
namespace
DoFactory.GangOfFour.Visitor.Structural
{
/// <summary>
/// MainApp startup class for Structural
/// Visitor Design Pattern.
/// </summary>
class MainApp
{
static void Main()
{
// Setup structure
ObjectStructure o = new ObjectStructure();
o.Attach(new ConcreteElementA());
o.Attach(new ConcreteElementB());
// Create visitor objects
ConcreteVisitor1 v1 = new ConcreteVisitor1();
ConcreteVisitor2 v2 = new ConcreteVisitor2();
// Structure accepting visitors
o.Accept(v1);
o.Accept(v2);
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// The 'Visitor' abstract class
/// </summary>
abstract class Visitor
{
public abstract void VisitConcreteElementA(
ConcreteElementA concreteElementA);
public abstract void VisitConcreteElementB(
ConcreteElementB concreteElementB);
}
/// <summary>
/// A 'ConcreteVisitor' class
/// </summary>
class ConcreteVisitor1 : Visitor
{
public override void VisitConcreteElementA(
ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} visited by {1}",
concreteElementA.GetType().Name, this.GetType().Name);
}
public override void VisitConcreteElementB(
ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} visited by {1}",
concreteElementB.GetType().Name, this.GetType().Name);
}
}
/// <summary>
/// A 'ConcreteVisitor' class
/// </summary>
class ConcreteVisitor2 : Visitor
{
public override void VisitConcreteElementA(
ConcreteElementA concreteElementA)
{
Console.WriteLine("{0} visited by {1}",
concreteElementA.GetType().Name, this.GetType().Name);
}
public override void VisitConcreteElementB(
ConcreteElementB concreteElementB)
{
Console.WriteLine("{0} visited by {1}",
concreteElementB.GetType().Name, this.GetType().Name);
}
}
/// <summary>
/// The 'Element' abstract class
/// </summary>
abstract class Element
{
public abstract void Accept(Visitor visitor);
}
/// <summary>
/// A 'ConcreteElement' class
/// </summary>
class ConcreteElementA : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementA(this);
}
public void OperationA()
{
}
}
/// <summary>
/// A 'ConcreteElement' class
/// </summary>
class ConcreteElementB : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementB(this);
}
public void OperationB()
{
}
}
/// <summary>
/// The 'ObjectStructure' class
/// </summary>
class ObjectStructure
{
private List<Element> _elements = new List<Element>();
public void Attach(Element element)
{
_elements.Add(element);
}
public void Detach(Element element)
{
_elements.Remove(element);
}
public void Accept(Visitor visitor)
{
foreach (Element element in _elements)
{
element.Accept(visitor);
}
}
}
}
下例範例以員工假日和收入之間的關係,用Visitor來呈現其之間的關係操作。
這個代碼演示Visitor模式中,橫越兩個物體員工的名單和每個員工執行相同的操作。這兩個Visitor對象定義不同的操作 -1調整休假日和其他收入。
using System;
using System.Collections.Generic;
namespace
DoFactory.GangOfFour.Visitor.RealWorld
{
/// <summary>
/// Visitor Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// 程式執行的啟動初始
/// </summary>
static void Main()
{
// 設定 employee collection
Employees e = new Employees();
e.Attach(new Clerk());
e.Attach(new Director());
e.Attach(new President());
// Employees are 'visited'
e.Accept(new IncomeVisitor());
e.Accept(new VacationVisitor());
// Wait for user
Console.ReadKey();
}
}
/// <summary>
/// 'Visitor' 的 interface
/// </summary>
interface IVisitor
{
void Visit(Element element);
}
/// <summary>
/// 'ConcreteVisitor' 的 class
/// </summary>
class IncomeVisitor : IVisitor
{
public void Visit(Element element)
{
Employee employee = element as Employee;
// Provide 10% pay raise
employee.Income *= 1.10;
Console.WriteLine("{0} {1}'s new income:
{2:C}",
employee.GetType().Name,
employee.Name,
employee.Income);
}
}
/// <summary>
/// 'ConcreteVisitor' 的 class
/// </summary>
class VacationVisitor : IVisitor
{
public void Visit(Element element)
{
Employee employee = element as Employee;
// 提供 3 個 extra vacation days
Console.WriteLine("{0} {1}'s new vacation days:
{2}",
employee.GetType().Name,
employee.Name,
employee.VacationDays);
}
}
/// <summary>
/// 'Element' abstract 的 class
/// </summary>
abstract class Element
{
public abstract void Accept(IVisitor visitor);
}
/// <summary>
/// 'ConcreteElement' 的 class
/// </summary>
class Employee : Element
{
private string _name;
private double _income;
private int _vacationDays;
// 建構函數
public Employee(string name, double income,
int vacationDays)
{
this._name = name;
this._income = income;
this._vacationDays = vacationDays;
}
// name的存取
public string Name
{
get { return _name; }
set { _name = value; }
}
// income的存取
public double Income
{
get { return _income; }
set { _income = value; }
}
// number of vacation
days的存取
public int VacationDays
{
get { return _vacationDays; }
set { _vacationDays = value; }
}
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
/// <summary>
/// 'ObjectStructure' 的 class
/// </summary>
class Employees
{
private List<Employee> _employees = new List<Employee>();
public void Attach(Employee employee)
{
_employees.Add(employee);
}
public void Detach(Employee employee)
{
_employees.Remove(employee);
}
public void Accept(IVisitor visitor)
{
foreach (Employee e in _employees)
{
e.Accept(visitor);
}
Console.WriteLine();
}
}
// 3個 employee types
class Clerk : Employee
{
// Constructor
public Clerk()
: base("Hank", 25000.0, 14)
{
}
}
class Director : Employee
{
// Constructor
public Director()
: base("Elly", 35000.0, 16)
{
}
}
class President : Employee
{
// Constructor
public President()
: base("Dick", 45000.0, 21)
{
}
}
}
-雲遊山水為知已逍遙一生而忘齡- 電腦神手
沒有留言:
張貼留言