首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构建通用物流系统

构建通用物流系统
EN

Stack Overflow用户
提问于 2017-05-22 08:32:32
回答 2查看 102关注 0票数 0

这是一个城市建设者游戏,但框架应该是有用的任何请求和发送。基本上,你有供应商和请求者。当请求者的需求不足时,就会提交请求。然后,每一个滴答,所有的请求都被处理,适当的供应商将他们的东西发送给适当的请求者,每个人都很高兴。我想做的是用仿制药来完成这一切。我对泛型相当在行,但已经有一段时间没有使用它们了,所以解决方案可能很简单。以下是一些代码:

代码语言:javascript
复制
public interface Requester<T> where T : Item
{
    bool NeedsToRequest();
    Request<T> LodgeRequest();
}

public interface Supplier<T> where T : Item
{
    void Supply(Request<T> request);
}

public class Request<T> where T : Item
{
    public Pile<T> Target;
    public int Amount;
}

所有这些都集中在一个大型中介类中,该类处理请求的生成和实现等。

代码语言:javascript
复制
public abstract class ProductionHandler
{ 
    public List<Supplier<Item>> Suppliers;

    public List<Request<Item>> Requests;

    public abstract bool TryRequest<T>(Request<T> request) where T : Item

}

同样相关的还有:

代码语言:javascript
复制
public class Pile<T> : List<T> where T : Item
{

    public int Amount
    {
        get { return this.Count; }
    }

}

最大的问题是按照T的类型对供应商进行排序,我想要查看请求的列表,获取它的类型,从列表中找到匹配的供应商类型,然后处理请求。另一个问题是,让你说你有“花:项目”和“玫瑰:花”和“向日葵:花”。如果有些东西需要鲜花,那么您可能希望将其发送到任意类型,因此,在这种情况下,仅仅比较类型就不那么容易了。如果有人能把我和一篇好文章联系起来,或者建议我如何安排一切,那就太好了,谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-22 08:59:30

在行中可以帮助进一步的第一步是使用方差,这样就可以将Supplier<Rose>转换为Supplier<Flower>Supplier<Item> (反之亦然)。如果不是这样,供应商必须是一个接口(ISupplier<out T> )。更多信息在这里:广义协方差与反方差

这样,您可以保留一个ISupplier<Item>列表,但要确保供应商是强类型的。这意味着列表只包含具有集合可转换的ISupplier<Rose>ISupplier<Sunflower>等项的直接实现,您可以简单地使用OfType<ISupplier<ItemType>>获取所需的供应商。

为了耦合请求,有几种可能性(例如在ISupplier上有2种类型,或者让接口与另一种类型公开另一种通用方法,并让供应商按添加的类型进行检查),但最干净的方法是为请求(IRequest<in T> )使用一个相反的接口,这可以在接口定义中使用。

示例设置:

代码语言:javascript
复制
public interface ISupplier<out T> 
{
    int Supply(IRequest<T> request);
}

public interface IRequest<in T> //request is input and is contravariant so it can be used in the ISupplier definition. Roughly said it means that if a specific type is used, it can also be used as input for any child type
{
    int Amount{get;set;}
}

public abstract class ProductionHandlerBase
{ 
    public List<ISupplier<Item>> Suppliers = new List<ISupplier<Item>>(); //ISupplier is covariant so any more derrived type (than Item) is still valid 

    public IEnumerable<ISupplier<T>> GetSuppliers<T>() //helper function to make calls easier, but Suppliers could be used directly as well
    {
        return Suppliers.OfType<ISupplier<T>>();
    }

    public bool TryRequest<T>(IRequest<T> Request)
        where T:Item
    {
        //example implementation. (neither optimized or necessariy logical, but it does show the expected types are used)
        foreach(var sup in GetSuppliers<T>())
        {
            if(sup.Supply(Request) > 0 && Request.Amount == 0)
                return true;
        }

        return false;
    }

    public void TestOutput()
    {
        Console.WriteLine(string.Join(", ", Suppliers));
    }
}

class ProductionHandlerExample:ProductionHandlerBase{}


public class Request<T>:IRequest<T>{
    public int Amount{get;set;}
}

public abstract class Supplier<T>:ISupplier<T>{
    int pileAmount = 4; //just to have an example
    public int Supply(IRequest<T> request) //example implementation
    {
        int cnt = Math.Min(request.Amount, pileAmount);
        if(cnt==0)return 0;
        pileAmount -= cnt;
        request.Amount -=cnt;
        return cnt;
    }

    public override string ToString() {return $"{typeof(T).Name}(s): {pileAmount}"; }
}

//items
public abstract class Item{}
public abstract class Flower:Item{}
public class Rose:Flower{}
public class SunFlower:Flower{}
public class Car:Item{}

//suppliers
public class Florist:Supplier<Flower>{} //implementation can still be on a class, as long as the collections are based on the covariant interface
public class Rosy:Supplier<Rose>{}
public class CarDealer:Supplier<Car>{}

示例用法:

代码语言:javascript
复制
var p = new ProductionHandlerExample();
p.Suppliers.Add(new Florist());
p.Suppliers.Add(new Rosy());
p.Suppliers.Add(new CarDealer());

//p.GetSuppliers<Flower>() -> Florist, Rosy
//p.GetSuppliers<Rose>() -> Rosy
//p.GetSuppliers<Item>() -> all items  (Florist, Rosy, CarDealer)

//in the example setup, each supplier has a pile of 4
p.TestOutput(); //Flower(s): 4, Rose(s): 4, Car(s): 4
p.TryRequest(new Request<Rose>{Amount = 2}); //returns true 
p.TestOutput(); //Flower(s): 4, Rose(s): 2, Car(s): 4
p.TryRequest(new Request<Car>{Amount = 5}); //returns false, there are only 4 cars
p.TestOutput(); //Flower(s): 4, Rose(s): 2, Car(s): 0
p.TryRequest(new Request<Flower>{Amount = 5}); //returns true, stock of both florist and Roses are used
p.TestOutput(); //Flower(s): 0, Rose(s): 1, Car(s): 0

在本例实现中,不执行子类型检查。如果花店里的花可能是玫瑰。这是因为该示例假定花的类型实际上并不为人所知。如果它是已知的,最好有一个通用的(I)Supplier和一个通用的TryRequest方法,其中每个实现检查自己的股票(Pile.OfType<>或类似的)。

票数 2
EN

Stack Overflow用户

发布于 2017-05-22 08:41:07

我认为这与您的TryRequest方法有关。在您的TryRequest<T>(Request<T> request) where T : Item实现中,您有T,所以您可以很容易地使用反射通过Suppliers

代码语言:javascript
复制
var supplier = Suppliers.FirstOrDefault
                   ( sup => sup.GetType()
                               .GenericTypeArguments[0] == typeof(T)
                   );

正如你所看到的,这不是很漂亮,但我现在没有更好的选择。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44108168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档