大話設計模式(帶目錄完整版)[中文PDF+源代碼].zip
下載地址:http://pan.baidu.com/s/1giQP4
大話設計模式C++.pdf
下載地址:http://pan.baidu.com/s/1ABbBv
大話設計模式C++源碼
下載地址:http://pan.baidu.com/s/1yzLBl
----------------------------------------------
剛剛看了訪問者模式,復雜問題簡單化。
class Node
{
accept(Visitro *pVisitor);
}
class Visitor
{
apply(Node *pNode){pNode->fun();}
}
------------------------------------------------
url:http://greatverve.cnblogs.com/p/Design-patterns-down.html
訪問者模式的目的: 封裝一些施加於某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構則可以保持不變。
問題的提出:System.Collection命名空間下提供了大量集合操作對象。平時我們大多在集合中都是存儲的同類型對象,像2.0中的泛型中就規定集合中只能存儲指定的對象類型,要么是整形要么是字符型等,否則會報錯。如果針對一個保存有不同類型對象的聚集采取某種操作該怎么辦呢?
示例:假設有一個員工報銷的集合,里面存儲了員工姓名和報銷金額情況,而報銷數據類型並不統一,有的是整形的,有的是雙精度的,有的是字符串型,我們要做的就是根據具體的數據類型給出不同的顯示格式,例如在整型數據后面加一個"C",(是我自己想的,整型的符號一時沒想起來),在雙數度數據后面加一個"D",浮點數據后面加"F",而字符串則什么也不加。
傳統實現方式:遍歷集合中的元素,判斷元素類型,然后做相應的處理。代碼如下:會發現就會出現必須對元素類型做類型判斷的條件轉移語句,如果判斷多了,要想維護起來也並不容易。此時可考慮采用訪問者模式。
_arr.Add( " 一百元 " );
_arr.Add( 100 );
_arr.Add( 150.5 );
foreach ( object o in _arr )
{
if (o is string )
{
Console.WriteLine(o.ToString());
}
else if (o is double )
{
Console .WriteLine (o.ToString () + " D " );
}
else if (o is Int32)
{
Console.WriteLine(o.ToString() + " C " );
}
}
訪問者模式適用性:
1:數據結構相對未定的系統,它把數據結構和作用於結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。
2:被訪問的類結構非常穩定的情況下使用。系統很少出現需要加入新節點的情況。如果出現需要加入新節點的情況,那么就必須在每一個訪問對象里加入一個對應於這個新節點的訪問操作,而這是對一個系統的大規模修改,因而是違背"開一閉"原則的。
訪問者模式的結構:
1:抽象訪問者(Visitor)角色:聲明了一個或者多個訪問操作,形成所有的具體元素角色必須實現的接口。
/// 抽象訪問者(Visitor)角色
/// </summary>
abstract class Visitor
{
// Methods
abstract public void Visit(Element element);
}
2:具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色所聲明的接口,也就是抽象訪問者所聲明的各個訪問操作。
/// 具體訪問者(ConcreteVisitor)角色
/// 打印雙精度數據
/// 在數據后面加 D
/// </summary>
class DoubleVisitor : Visitor
{
// Methods
public override void Visit(Element element)
{
Employee employee = ((Employee)element);
if (employee._Data.GetType().ToString () != " System.Double " )
{ return ; }
Console.WriteLine( " {0}'s data: {1}D " ,
employee.Name, employee._Data );
}
}
/// <summary>
/// 具體訪問者(ConcreteVisitor)角色2
/// 打印整型數據
/// 在數據后面加 C
/// </summary>
class Int32Visitor : Visitor
{
public override void Visit(Element element)
{
Employee employee = ((Employee)element);
if (employee._Data.GetType().ToString() != " System.Int32 " )
{ return ; }
Console.WriteLine( " {0}'s data : {1}C " ,
employee.Name, employee._Data );
}
}
3:抽象節點(Node)角色:聲明一個接受操作,接受一個訪問者對象作為一個參量。
/// 抽象節點(Node)角色
/// </summary>
abstract class Element
{
// Methods
abstract public void Accept(Visitor visitor);
}
4:具體節點(Node)角色:實現了抽象元素所規定的接受操作。
/// 具體節點(Node)角色
/// </summary>
class Employee : Element
{
// Fields
string name;
private object _data;
public object _Data
{
get { return this ._data ; }
set { this ._data = value; }
}
// Constructors
public Employee( string _name, object t)
{
this .name = _name;
this ._Data = t;
}
// Properties
public string Name
{
get { return name; }
set { name = value; }
}
// Methods
public override void Accept(Visitor visitor)
{
visitor.Visit( this );
}
}
5:結構對象(ObiectStructure)角色:有如下的一些責任,可以遍歷結構中的所有元素;如果需要,提供一個高層次的接口讓訪問者對象可以訪問每一個元素;如果需要,可以設計成一個復合對象或者一個聚集。
/// 結構對象(ObiectStructure)角色
/// </summary>
class Employees
{
// Fields
private ArrayList employees = new ArrayList();
// Methods
public void Attach(Employee employee)
{
employees.Add(employee);
}
public void Detach(Employee employee)
{
employees.Remove(employee);
}
public void Accept(Visitor visitor)
{
foreach (Employee e in employees)
e.Accept(visitor);
}
}
6:客戶端代碼:
Employees e = new Employees();
e.Attach( new Employee( " 用戶A: " , 25000.0 ));
e.Attach( new Employee( " 用戶B: " , 10000 ));
e.Attach( new Employee( " 用戶C: " , " 45000.0RMB " ));
// Create two visitors
DoubleVisitor v1 = new DoubleVisitor();
Int32Visitor v2 = new Int32Visitor();
StringVisitor v3 = new StringVisitor();
// Employees are visited
e.Accept(v1);
e.Accept(v2);
e.Accept(v3);
結構對象會遍歷它自己所保存的聚集中的所有節點,在本系統中只有一個節點Employee。這個訪問是由以下的操作組成的:
1. Employee對象的接受方法Accept被調用;
2. Employee對象反過來調用訪問者對象的Visit方法,並將對象本身傳入;
3. 訪問者對象調用本身的Visit方法。
訪問者模式有如下的優點:
1. 訪問者模式使得增加新的操作變得很容易。如果一些操作依賴於一個復雜的結構對象的話,那么一般而言,增加新的操作會很復雜。而使用訪問者模式,增加新的操作就意味着增加一個新的訪問者類,因此,變得很容易。
2. 訪問者模式將有關的行為集中到一個訪問者對象中,而不是分散到一個個的節點類中。
3. 訪問者模式可以跨過幾個類的等級結構訪問屬於不同的等級結構的成員類。迭代子只能訪問屬於同一個類型等級結構的成員對象,而不能訪問屬於不同等級結構的對象。訪問者模式可以做到這一點。
4. 積累狀態。每一個單獨的訪問者對象都集中了相關的行為,從而也就可以在訪問的過程中將執行操作的狀態積累在自己內部,而不是分散到很多的節點對象中。這是有益於系統維護的優點。
訪問者模式有如下的缺點:
1. 增加新的節點類變得很困難。每增加一個新的節點都意味着要在抽象訪問者角色中增加一個新的抽象操作,並在每一個具體訪問者類中增加相應的具體操作。
2. 破壞封裝。訪問者模式要求訪問者對象訪問並調用每一個節點對象的操作,這隱含了一個對所有節點對象的要求:它們必須暴露一些自己的操作和內部狀態。不然,訪問者的訪問就變得沒有意義。由於訪問者對象自己會積累訪問操作所需的狀態,從而使這些狀態不再存儲在節點對象中,這也是破壞封裝的。
注:
本文引用:《Java與模式》
http://www.cnblogs.com/zhenyulu/articles/79719.html