簡體   English   中英

將復合模式應用於一般圖形模型

[英]apply composite pattern to general graph models

我想建一個數據model,主要是一個圖,后面要遍歷。 特殊要求:圖中的節點可以是要執行的動作,也可以是帶有另一個動作或容器圖的容器。 在遍歷過程中,必須檢查當前節點是否是容器,如果是,則開始子圖的遍歷。

這是如何實現的? 數據 model 應該是什么樣子,才能構建出如下圖所示的結構?

在此處輸入圖像描述

到目前為止,我已經上了一些課。 有幾種動作類型,因此我在這里使用一個接口

public interface IAction : IContainer
{
    public ActionType ActionType{ get; set; }
    public Name { get; set; }
}

該容器僅包含一個名稱和一個自我引用。 我最初也嘗試通過使用接口來完成此操作,但后來我只能訪問接口屬性,而不能訪問容器屬性

public interface IContainer
{
    public string Name { get; set; }
}

public class Container : IContainer
{
    public string Name { get; set; }
    public IContainer Content { get; set; }
}

主要的測試用法如下所示:

myJob.Content = new QuikGraph.BidirectionalGraph<IContainer, QuikGraph.Edge<IContainer>>();
myJob.Content.AddVertex(new MyCustomAction()
{
    ActionType = ActionType.MyCustomAction,
    Name = "Test"
});

myJob.Content.Vertices.First().Name // only property I could access, no action-specific ones

我究竟做錯了什么?

我相信您在IContainer中缺少一個操作(一種方法),該操作可以從圖中的任何節點調用,並且可以按您預期的方式運行(一個容器將調用轉發到其所有包含的操作和一個執行實際操作的操作)。

此外,與其在Container中持有對IContainer的單個引用,不如擁有子IContainer的集合,因為在您的圖表中,容器有 3 個操作。

有關更多說明,請參閱復合模式

public interface IContainer
{
    string Name { get; set; }
    void DoWork();
}

public sealed class Action1 : IAction
{
    public override DoWork()
    {
        //Do the real work
    }
}

public sealed class Container : IContainer
{
    private readonly IReadOnlyList<IContainer> _children;
    public Container(IEnumerable<IContainer> children) => _children = children.ToList();
    public override DoWork()
    {
        foreach(var child in _children)
        {
            child.DoWork();
        }
    }
}

這就是我想出的結果。 我花了一些時間才知道如何 model 這個,但最終我按照@Spotted 的建議應用了復合模式。 我從類中完全刪除了 quikgraph 庫並將其外包給另一個服務,我只在我想遍歷圖形或檢查循環等時調用它......

此外,我選擇不直接將實體相互鏈接,而是通過名稱鏈接,否則序列化會輸出雙倍的信息(節點可能被多次引用)。

public interface IContainer
{
    string Name { get; set; }
    IList<string> DependsOn { get; set; }
    void DoWork();
    void AddDependency(string name)
}

public interface IAction : IContainer
{
    // more common stuff
}

public sealed class Action1 : IAction
{
    public string Name { get; set; }
    IList<string> DependsOn { get; set; }
    public DoWork()
    {
        //Do the real work
    }
    
    public void AddDependency(string name)
    {
        this.DependsOn.Add(name);
    }
}

public sealed class Container : IContainer
{
    public string Name { get; set; }
    public IList<string> DependsOn { get; set; }
    public IList<IContainer> SubGraph { get; set; }

    public override DoWork()
    {
        foreach(var item in SubGraph)
        {
            item.DoWork();
        }
    }

    public void AddSubGraph(IList<IContainer> subGraph)
    {
        this.SubGraph = subGraph;
    }
}

謝謝你的幫助,伙計!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM