2 回答

TA貢獻(xiàn)1869條經(jīng)驗 獲得超4個贊
在代碼項目中對此進(jìn)行了廣泛的研究 -訪客模式重新解釋。
我將提供標(biāo)題。
訪問者模式是為了解決問題,通過呈現(xiàn)兩個方面:
有一個迭代機(jī)制,它知道如何迭代對象hirerachy。它對層次結(jié)構(gòu)中對象的行為一無所知。
需要實現(xiàn)的新行為對迭代機(jī)制一無所知,它們不知道如何迭代對象層次結(jié)構(gòu)。
現(xiàn)在這兩個方面,是相互獨立的,不應(yīng)該相互混淆。所以,這一切都是關(guān)于稱為單一責(zé)任主體的 OOP 主體,帶您回到SOLID 架構(gòu)。
此功能的主要參與者是:
訪問者- 定義訪問操作的接口。這是訪問者模式的核心。它為對象結(jié)構(gòu)中的每種類型的 Concreate Element 定義了一個訪問操作。
ConcreateVisitor - 實現(xiàn)在訪問者接口中定義的操作。
ElementBase:它是一個抽象/接口,它定義了以訪問者為參數(shù)的 Accept 操作。
ConcreateElement - 這些類型實現(xiàn)了 Element 接口的 Accept 方法。
對象結(jié)構(gòu)——它將數(shù)據(jù)結(jié)構(gòu)的所有元素保存為集合、列表或訪問者可以枚舉和使用的東西。它為所有訪問者提供訪問其元素的界面。這些元素包括稱為“接受”的方法。然后枚舉集合
現(xiàn)在,所有這些模式的目標(biāo),關(guān)鍵是創(chuàng)建功能有限的數(shù)據(jù)模型和一組具有特定功能的訪問者,這些訪問者將對數(shù)據(jù)進(jìn)行操作。該模式允許訪問者訪問數(shù)據(jù)結(jié)構(gòu)的每個元素,并將對象作為參數(shù)傳遞給訪問者方法。
畢竟的好處-
將算法與其數(shù)據(jù)模型分離的關(guān)鍵是能夠輕松添加新行為。數(shù)據(jù)模型的類是使用名為 Visit 的公共方法創(chuàng)建的,該方法可以在運行時接受訪問者對象。然后可以創(chuàng)建不同的訪問者對象并將其傳遞給此方法,然后此方法對訪問者方法有一個回調(diào),將自身作為參數(shù)傳遞給它。
另一件值得一提的是:
向?qū)ο髮哟谓Y(jié)構(gòu)添加新類型需要更改所有訪問者,這應(yīng)該被視為一個優(yōu)勢,因為它肯定會迫使我們將新類型添加到您保留某些特定于類型代碼的所有位置?;旧纤恢皇亲屇阃涍@一點。
訪問者模式僅有用:
如果您要實現(xiàn)的接口是相當(dāng)靜態(tài)的并且不會發(fā)生太大變化。
如果預(yù)先知道所有類型,即在設(shè)計時必須知道所有對象。
在底線:
訪客實現(xiàn)以下設(shè)計原則:
關(guān)注點分離 - 訪問者模式促進(jìn)了這一原則,將多個方面/關(guān)注點分離到多個其他類,因為它鼓勵更簡潔的代碼和代碼可重用性,并且代碼更易于測試。
單一職責(zé)原則 - 訪問者模式也強(qiáng)制執(zhí)行此原則。一個對象應(yīng)該有幾乎一個責(zé)任。不相關(guān)的行為必須從它分離到另一個類。
開閉原則——訪問者模式也遵循這個原則,就好像,我們要擴(kuò)展一個對象的行為一樣,原來的源代碼是沒有改變的。訪問者模式為我們提供了將其分離到另一個類并在運行時將這些操作應(yīng)用于對象的機(jī)制。
訪客實施的好處是:
將數(shù)據(jù)結(jié)構(gòu)的行為與它們分開。創(chuàng)建單獨的訪問者對象以實現(xiàn)此類行為。
它解決了很少面臨但具有重要影響的雙重調(diào)度問題。
您可以深入研究這篇文章以了解其全部含義,但如果我要舉一個例子:
首先,我們將定義我們稱為 IVisitable 的接口。它將定義一個接受 IVisitor 參數(shù)的 Accept 方法。該接口將作為產(chǎn)品列表中所有類型的基礎(chǔ)。所有類型,如 Book、Car 和 Wine(在我們的示例中)都將實現(xiàn)此類型。
/// <summary>
/// Define Visitable Interface.This is to enforce Visit method for all items in product.
/// </summary>
internal interface IVisitable
{
void Accept(IVisitor visit);
}
然后我們將實現(xiàn)它:
#region "Structure Implementations"
/// <summary>
/// Define base class for all items in products to share some common state or behaviors.
/// Thic class implement IVisitable,so it allows products to be Visitable.
/// </summary>
internal abstract class Product : IVisitable
{
public int Price { get; set; }
public abstract void Accept(IVisitor visit);
}
/// <summary>
/// Define Book Class which is of Product type.
/// </summary>
internal class Book : Product
{
// Book specific data
public Book(int price)
{
this.Price = price;
}
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
/// <summary>
/// Define Car Class which is of Product type.
/// </summary>
internal class Car : Product
{
// Car specific data
public Car(int price)
{
this.Price = price;
}
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
/// <summary>
/// Define Wine Class which is of Product type.
/// </summary>
internal class Wine : Product
{
// Wine specific data
public Wine(int price)
{
this.Price = price;
}
public override void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
#endregion "Structure Implementations"
創(chuàng)建一個訪問者界面并實現(xiàn)它:
/// <summary>
/// Define basic Visitor Interface.
/// </summary>
internal interface IVisitor
{
void Visit(Book book);
void Visit(Car car);
void Visit(Wine wine);
}
#region "Visitor Implementation"
/// <summary>
/// Define Visitor of Basic Tax Calculator.
/// </summary>
internal class BasicPriceVisitor : IVisitor
{
public int taxToPay { get; private set; }
public int totalPrice { get; private set; }
public void Visit(Book book)
{
var calculatedTax = (book.Price * 10) / 100;
totalPrice += book.Price + calculatedTax;
taxToPay += calculatedTax;
}
public void Visit(Car car)
{
var calculatedTax = (car.Price * 30) / 100;
totalPrice += car.Price + calculatedTax;
taxToPay += calculatedTax;
}
public void Visit(Wine wine)
{
var calculatedTax = (wine.Price * 32) / 100;
totalPrice += wine.Price + calculatedTax;
taxToPay += calculatedTax;
}
}
#endregion "Visitor Implementation"
執(zhí)行:
static void Main(string[] args)
{
Program.ShowHeader("Visitor Pattern");
List<Product> products = new List<Product>
{
new Book(200),new Book(205),new Book(303),new Wine(706)
};
ShowTitle("Basic Price calculation");
BasicPriceVisitor pricevisitor = new BasicPriceVisitor();
products.ForEach(x =>
{
x.Accept(pricevisitor);
});
Console.WriteLine("");
}

TA貢獻(xiàn)1820條經(jīng)驗 獲得超9個贊
當(dāng)你有一個多態(tài)類型并且你想根據(jù)對象的特定子類型執(zhí)行外部定義的操作時,通常使用訪問者模式。在您的示例中,CoursesResult是一個多態(tài)類型,訪問者允許您將Successful響應(yīng)轉(zhuǎn)換為一個,OkObjectResult而無需直接耦合這兩種類型。
您CoursesResult直接返回 an 的替代方法IActionResult是傳統(tǒng)的多態(tài)性,它更簡單,但將域邏輯耦合到 MVC 層。
現(xiàn)在,我不知道您的全套響應(yīng)是什么樣的,但是如果您只有一個成功響應(yīng),其余都是錯誤,那么這里最簡單的方法是直接返回成功響應(yīng)并為其他情況拋出異常:
public async Task<CourseList> GetCourses(UserSession userSession) {
return courseList; /* or */ throw new BadRequestException();
}
然后您的控制器可以簡單地捕獲異常并將它們轉(zhuǎn)換為適當(dāng)?shù)腎ActionResult.
- 2 回答
- 0 關(guān)注
- 108 瀏覽
添加回答
舉報