Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不破坏类结构的情况下对包含类中的操作进行矢量化_C#_Design Patterns - Fatal编程技术网

C# 在不破坏类结构的情况下对包含类中的操作进行矢量化

C# 在不破坏类结构的情况下对包含类中的操作进行矢量化,c#,design-patterns,C#,Design Patterns,我当前的项目被分为多个类,这些类正确地表示了我们对系统中实体的看法。然而,这是以性能为代价的,所以我试图提出一种在保持现有的类结构的同时提高性能的方法 我认为一个例子最能说明这个问题:假设我有一个Order类,它包含多个项s。运送订单的一个简单实现是运送其所有项目s: class Order { private List<Item> m_items; public void Ship() { foreach (Item item in m_

我当前的项目被分为多个类,这些类正确地表示了我们对系统中实体的看法。然而,这是以性能为代价的,所以我试图提出一种在保持现有的类结构的同时提高性能的方法

我认为一个例子最能说明这个问题:假设我有一个
Order
类,它包含多个
s。运送
订单
的一个简单实现是运送其所有
项目
s:

class Order 
{
    private List<Item> m_items;

    public void Ship()
    {
        foreach (Item item in m_items)
        {
            item.Ship();
        }
    }
}
事实证明,在
船上运送
项目
需要很长时间。幸运的是,
可以同时运送多个
项目
列出Boat.ShipToDestination(列出项目)
)。但是,要使用此方法,我必须重写
Order.Ship()
,如下所示:

class Order 
{
    public void Ship()
    {
        var receipts = m_boat.ShipToDestination(m_items);
        foreach (Receipt receipt in receipts)
        {
            ProcessReceipt(receipt);
        }
    }
}
这意味着
处理收据
现在是
订单
(而不是
项目
)的一部分,而且
项目
不再负责其所有运输物流

在我的实际代码中,有很多方法可以解决这个问题,因此有效地使用这个解决方案意味着大多数
逻辑将进入
顺序
类。然而,这似乎是一个错误的地方有这种逻辑-它真的应该在
项目

我考虑过使用多个线程(例如,每个
项目使用
任务
),但这似乎太浪费了,特别是因为
订单
可以有几十个
项目

我考虑的另一种方法是使用
QueueForShipping(Item Item)
方法和
ShipQueuedItems()
方法创建
QueuedBoat
。现在,
Order
可以调用
ShipQueuedItems
,而
Item
可以调用
QueueForShipping
。这种方法的问题是,在我的真实代码中,
收据
仅在
项目
发货后返回,因此代码必须如下所示:

class Order 
{
    private List<Item> m_items;

    public void Ship()
    {
        foreach (Item item in m_items)
        {
            item.Ship();
        }

        m_queuedBoat.ShipQueuedItems();

        foreach (Item item in m_items)
        {
            item.FinalizeShipping();
        }
    }
}


class Item
{
    public void Ship()
    {
        m_queuedBoat.QueueForShipping(this);
    }

    public void FinalizeShipping()
    {
        ProcessReceipt(m_queuedBoat.GetReceiptForItem(this));
    }
}

QueuedBoat
类使用其
收据调用每个项目的回调时,无论如何
Ship
是一种异步操作:必须同时运行多个项目。因此必须分为两个阶段:
PrepareShipping
(作废)和
PerformShipping
(等待实际发货完成并返回处理其收据)

我想这样说:

class Item
{
    public void PrepareShiping()
    {
        m_queuedBoat.QueueForShipping(this);
    }

    public void PerformShipping()
    {
        m_queuedBoat.StartActualShippingIfNotAlreadyStarted();
        m_queuedBoat.WaitForShippingEnd();
        ProcessReceipt(m_queuedBoat.GetReceiptForItem(this));
    }
}
class Order 
{
    public void PrepareShipping()
    {
        foreach (Item item in m_items)
            item.PrepareShiping();
    }

    public void PerformShipping()
    {
        foreach (Item item in m_items)
            item.PerformShipping();
    }

    // and for those who don't need asynchronity
    public void Ship()
    {
        PrepareShipping();
        PerformShipping();
    }
}
所以顺序可以是这样的:

class Item
{
    public void PrepareShiping()
    {
        m_queuedBoat.QueueForShipping(this);
    }

    public void PerformShipping()
    {
        m_queuedBoat.StartActualShippingIfNotAlreadyStarted();
        m_queuedBoat.WaitForShippingEnd();
        ProcessReceipt(m_queuedBoat.GetReceiptForItem(this));
    }
}
class Order 
{
    public void PrepareShipping()
    {
        foreach (Item item in m_items)
            item.PrepareShiping();
    }

    public void PerformShipping()
    {
        foreach (Item item in m_items)
            item.PerformShipping();
    }

    // and for those who don't need asynchronity
    public void Ship()
    {
        PrepareShipping();
        PerformShipping();
    }
}

程序可以在发货过程中执行其他操作,即在
订单.PrepareShipping()
订单.PerformShipping()
之间(例如,也可以在同一艘船上发货其他订单).

在C#5中,它将更容易:人们将能够使
发送
任务
并使用新的异步/等待技术异步启动它。(将名称从Begin/End更改为Prepare/Perform)这是一种有趣的方法。我喜欢它的地方在于它不需要
Order
访问
QueuedBoat
就可以开始发货。但是,它仍然需要我将
Item.Ship
拆分为多个阶段(在人为示例中为两个阶段,在实际代码中为三个或四个阶段)。请注意,这里的一切都是同步的:将要发货的项目逐个排队,然后我们发货,然后我们处理收据。刚刚意识到“同时发货其他订单”的意思。这很有趣,因为这实际上是我们想到的向量化的下一个阶段:在同一艘
船上从多个
订单
s运送
Item
s。telewin:嗯,你不能将
Item.ship
作为一个操作,否则它会将整艘船作为一个项目,因为该项目不知道其他项目。应该有一个运输经理来处理这个问题,在我的代码中这是订单,它调用first PrepareShipping,并且只调用PerformShipping。@telewin:好的,我会将isLast重命名为
shouldTriggerPerform
,并将其作为
订单的参数。Ship
也:public void Ship(bool shouldTriggerPerform){for(int i=0;i