2 回答

TA貢獻1869條經驗 獲得超4個贊
在代碼項目中對此進行了廣泛的研究 -訪客模式重新解釋。
我將提供標題。
訪問者模式是為了解決問題,通過呈現兩個方面:
有一個迭代機制,它知道如何迭代對象hirerachy。它對層次結構中對象的行為一無所知。
需要實現的新行為對迭代機制一無所知,它們不知道如何迭代對象層次結構。
現在這兩個方面,是相互獨立的,不應該相互混淆。所以,這一切都是關于稱為單一責任主體的 OOP 主體,帶您回到SOLID 架構。
此功能的主要參與者是:
訪問者- 定義訪問操作的接口。這是訪問者模式的核心。它為對象結構中的每種類型的 Concreate Element 定義了一個訪問操作。
ConcreateVisitor - 實現在訪問者接口中定義的操作。
ElementBase:它是一個抽象/接口,它定義了以訪問者為參數的 Accept 操作。
ConcreateElement - 這些類型實現了 Element 接口的 Accept 方法。
對象結構——它將數據結構的所有元素保存為集合、列表或訪問者可以枚舉和使用的東西。它為所有訪問者提供訪問其元素的界面。這些元素包括稱為“接受”的方法。然后枚舉集合
現在,所有這些模式的目標,關鍵是創建功能有限的數據模型和一組具有特定功能的訪問者,這些訪問者將對數據進行操作。該模式允許訪問者訪問數據結構的每個元素,并將對象作為參數傳遞給訪問者方法。
畢竟的好處-
將算法與其數據模型分離的關鍵是能夠輕松添加新行為。數據模型的類是使用名為 Visit 的公共方法創建的,該方法可以在運行時接受訪問者對象。然后可以創建不同的訪問者對象并將其傳遞給此方法,然后此方法對訪問者方法有一個回調,將自身作為參數傳遞給它。
另一件值得一提的是:
向對象層次結構添加新類型需要更改所有訪問者,這應該被視為一個優勢,因為它肯定會迫使我們將新類型添加到您保留某些特定于類型代碼的所有位置。基本上它不只是讓你忘記這一點。
訪問者模式僅有用:
如果您要實現的接口是相當靜態的并且不會發生太大變化。
如果預先知道所有類型,即在設計時必須知道所有對象。
在底線:
訪客實現以下設計原則:
關注點分離 - 訪問者模式促進了這一原則,將多個方面/關注點分離到多個其他類,因為它鼓勵更簡潔的代碼和代碼可重用性,并且代碼更易于測試。
單一職責原則 - 訪問者模式也強制執行此原則。一個對象應該有幾乎一個責任。不相關的行為必須從它分離到另一個類。
開閉原則——訪問者模式也遵循這個原則,就好像,我們要擴展一個對象的行為一樣,原來的源代碼是沒有改變的。訪問者模式為我們提供了將其分離到另一個類并在運行時將這些操作應用于對象的機制。
訪客實施的好處是:
將數據結構的行為與它們分開。創建單獨的訪問者對象以實現此類行為。
它解決了很少面臨但具有重要影響的雙重調度問題。
您可以深入研究這篇文章以了解其全部含義,但如果我要舉一個例子:
首先,我們將定義我們稱為 IVisitable 的接口。它將定義一個接受 IVisitor 參數的 Accept 方法。該接口將作為產品列表中所有類型的基礎。所有類型,如 Book、Car 和 Wine(在我們的示例中)都將實現此類型。
/// <summary>
/// Define Visitable Interface.This is to enforce Visit method for all items in product.
/// </summary>
internal interface IVisitable
{
void Accept(IVisitor visit);
}
然后我們將實現它:
#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"
創建一個訪問者界面并實現它:
/// <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"
執行:
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貢獻1820條經驗 獲得超9個贊
當你有一個多態類型并且你想根據對象的特定子類型執行外部定義的操作時,通常使用訪問者模式。在您的示例中,CoursesResult是一個多態類型,訪問者允許您將Successful響應轉換為一個,OkObjectResult而無需直接耦合這兩種類型。
您CoursesResult直接返回 an 的替代方法IActionResult是傳統的多態性,它更簡單,但將域邏輯耦合到 MVC 層。
現在,我不知道您的全套響應是什么樣的,但是如果您只有一個成功響應,其余都是錯誤,那么這里最簡單的方法是直接返回成功響應并為其他情況拋出異常:
public async Task<CourseList> GetCourses(UserSession userSession) {
return courseList; /* or */ throw new BadRequestException();
}
然后您的控制器可以簡單地捕獲異常并將它們轉換為適當的IActionResult.
- 2 回答
- 0 關注
- 103 瀏覽
添加回答
舉報