工厂在一个项目中应该住在哪里

本文关键字:在哪里 项目 一个 工厂 | 更新日期: 2023-09-27 18:07:09

我有一个名为MudEngine.Core的项目的解决方案。这个项目包含一些基本的类,然后是我的域对象抽象在后面的所有接口。像IWorldIRealm这样的接口。

域接口示例

public interface IWorld : IGameComponent, ICloneableComponent<IWorld>
{
    /// <summary>
    /// Gets how many hours it takes to complete one full day in this world.
    /// </summary>
    int HoursPerDay { get; }
    /// <summary>
    /// Gets or sets the game day to real hour ratio.
    /// </summary>
    double GameDayToRealHourRatio { get; set; }
    /// <summary>
    /// Adds a collection of realms to world, initializing them as they are added.
    /// </summary>
    /// <param name="realms">The realms.</param>
    /// <returns>
    /// Returns an awaitable Task
    /// </returns>
    IRealm[] GetRealmsInWorld();
    /// <summary>
    /// Initializes and then adds the given realm to this world instance.
    /// </summary>
    /// <param name="realm">The realm to add.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task AddRealmToWorld(IRealm realm);
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner);
    /// <summary>
    /// Adds a collection of realms to world, initializing them as they are added.
    /// </summary>
    /// <param name="realms">The realms.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task AddRealmsToWorld(IEnumerable<IRealm> realms);
    /// <summary>
    /// Removes the given realm from this world instance, deleting the realm in the process.
    /// If it must be reused, you may clone the realm and add the clone to another world.
    /// </summary>
    /// <param name="realm">The realm to remove.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task RemoveRealmFromWorld(IRealm realm);
    /// <summary>
    /// Removes a collection of realms from this world instance.
    /// If any of the realms don't exist in the world, they will be ignored.
    /// The realms will be deleted during the process.
    /// If they must be reused, you may clone the realm and add the clone to another world.
    /// </summary>
    /// <param name="realms">The realms collection.</param>
    /// <returns>Returns an awaitable Task</returns>
    Task RemoveRealmsFromWorld(IEnumerable<IRealm> realms);
}

我还有一个名为MudEngine.Mud的项目,它是所有接口的默认实现。

MudEngine.Core项目包括我的工厂的接口。像IWorldFactoryIRealmFactory这样的工厂。IWorld接口有一个创建方法,使用给定的IRealmFactory创建领域并返回它们。

工厂界面示例

/// <summary>
/// Provides methods for creating an instance of an IRealm implementation
/// </summary>
public interface IRealmFactory
{
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner);
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="timeZoneOffset">The time zone offset to apply to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, ITimeOfDay timeZoneOffset);
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// All of the children zones will be initialized prior to being added to the realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="zones">A collection of zones that will be initialized and added to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, IEnumerable<IZone> zones);
    /// <summary>
    /// Creates and initializes a new instance of a realm.
    /// All of the children zones will be initialized prior to being added to the realm.
    /// </summary>
    /// <param name="name">The name of the realm.</param>
    /// <param name="owner">The world that owns this realm.</param>
    /// <param name="timeZoneOffset">The time zone offset to apply to the realm.</param>
    /// <param name="zones">A collection of zones that will be initialized and added to the realm.</param>
    /// <returns>Returns an initialized instance of IRealm</returns>
    Task<IRealm> CreateRealm(string name, IWorld owner, ITimeOfDay timeZoneOffset, IEnumerable<IZone> zones);
}

当我在IWorld接口上调用CreateRealm时,实现使用IRealmFactory来创建它。工厂是通过IWorld实现的构造函数传入的。

我现在的问题是,工厂实施应该存在于哪里?包含域接口实现的同一项目为工厂提供实现是常见的吗?还是消费层(如演示/单元测试项目(应该负责实现工厂并使用它们?

其目的是,这些组件可以根据您正在构建的基于文本的游戏的类型进行交换。所以我倾向于每个实现接口的包都有自己的工厂。不过,我关心的是DI设置。更上层的IoC容器(服务器/客户端应用程序(需要知道它应该使用每个包中的哪个工厂,而不是只使用IoC容器所属的消费层中定义的工厂。

这方面有什么行业标准指南吗?

工厂在一个项目中应该住在哪里

你似乎正在尝试用抽象的子域建立一个域模型(我想你可以称它们为子域,因为它们是成熟的游戏系统(,即用户可以在运行时动态选择一个子域,这会触发一些子域不可知的行为,然后在一段时间内用它做子域特定的事情,完成后可能会跳到另一个子域。

尽管根据我的经验,你很少在"正常"的业务项目中遇到这种情况,但我会这样做:

  • 为通用的世界和领域管理创建一个总体的有边界的上下文。把IWorldIRealmFactory放在那里。

  • 为每个游戏系统子域创建一个单独的边界上下文。它们可以是整个项目,也可以只是名称空间。在其中编写IRealmFactory的实现。

  • 这是我认为使用Container.Resolve(...)可以合法使用的少数实例之一。在IoC配置中创建命名注册,并随时解析其中一个注册,以连接对应于一个游戏系统的对象子图。