gpt4 book ai didi

c# - 是否有更好的设计来公开您不想直接实现的基本接口(interface)?

转载 作者:行者123 更新时间:2023-11-30 17:30:02 25 4
gpt4 key购买 nike

我正在创建一个 API,允许某人构建带有 optional 的菜单。 API 库本身没有任何呈现逻辑,只有描述选项所需的信息。这样,此 API 的使用者可以将其添加为依赖项,渲染器库也可以将其添加为依赖项。然后渲染器可以根据消费者创建的对象渲染菜单。

是这样的:

public interface IOptionGroup
{
List<IOption> Options { get; }
}

public interface IOption
{
//Some Shared attributes for all Options
}

public interface IOptionCheckbox : IOption
{
// Some checkbox specific attributes
void OnValueChanged(bool newValue);
}

公开基础接口(interface):

拥有基础 IOption 接口(interface)很好,因为它包含所有不同选项类型的所有共享属性,但只有 API 的用户实现从 IOption 派生的接口(interface)才有意义。如果他们自己实现了 IOption 并将其作为 Options 之一传回,则没有足够的信息来实际将有效的 Option 绘制到菜单。

在渲染期间向上转换:

此外,这种设计迫使我向上转换接口(interface)以确定要呈现的选项类型(这感觉不对)。另外,如果他们实现多个 Option 接口(interface)怎么办?!?

foreach(IOption option in group.Options) 
{
if (option is IOptionCheckbox)
{
// Render a Checkbox
} else if (option is ...)
{
// Render a ...
}
}

使用案例让它更清晰:

我希望客户端能够实现描述菜单项的接口(interface),而无需了解有关呈现它们的任何信息。对于不同的选项,他们会得到不同的回调:

示例客户端代码:

public class MyCheckBox : IOptionCheckbox
{
void OnValueChanged(bool newValue)
{
// Do something specific here when user checks/unchecks option
}
}

客户端只需要关心当复选框被点击时要做什么。我不能在 IOption 接口(interface)中放置渲染器,因为那样需要客户端自己实现渲染器。

最佳答案

我还没有想出一个完美的方法来做我想做的事,但我会把我的答案分成两个选项,每个选项都有优缺点。如果您正在寻找自己的类似问题的解决方案,您可能希望选择选项 1。


选项 1:良好的界面

这里的主要问题(正如@Servy 指出的那样)是接口(interface)应该真正包含执行其预期目的所需的每个操作。上面的例子看起来像这样:

public interface IRenderer
{
void Draw(/* Params needed to draw */);
}

public interface IOption
{
//Some Shared attributes for all Options
IRenderer Renderer { get; }
}

渲染库然后可以提供(可能是抽象的)接口(interface)的实现,这些接口(interface)派生自 IOption,客户端可以使用这些接口(interface)来渲染选项,或者继承并覆盖或简单地实例化和使用。

渲染器代码:

public abstract class RendererOptionCheckbox : IOptionCheckbox
{
public IRenderer Renderer => new CheckboxRender();

public abstract void OnValueChanged(bool newValue);
}

客户代码:

public class MyCheckBox : RendererOptionCheckbox
{
void OnValueChanged(bool newValue)
{
// Do something specific here when user checks/unchecks option
}
}

优点:

  • 无需向上转换以呈现 IOption 列表,因为每个选项都知道如何呈现自身
  • 暴露基本 IOption 接口(interface)没有问题,因为如果客户端尝试使用它,则必须定义渲染器
  • 客户端可以使用自定义呈现逻辑注入(inject)他们自己的自定义 IOption

缺点:

  • 客户端可以使用自定义呈现逻辑注入(inject)他们自己的自定义 IOption(这是一把双刃剑,您可能不希望这样)
  • 客户端需要实例化直接从渲染器继承的对象,使实际渲染器和客户端之间的耦合比我想要的更紧密。

选项 2:记录您的问题

只需按照原始问题中的描述编写代码,使用向上转换执行渲染,如果直接实现 IOption 则抛出详细的异常,并提供有效使用与无效使用类的良好文档(如@DanWilson 所建议的) .

优点:

  • 从客户的角度来看界面简洁(看不到渲染逻辑)
    • 客户端可以使用接口(interface)而不用担心要实例化或继承哪些相关的渲染器特定类
    • 无需更改客户端代码即可轻松更换渲染器

缺点:

  • 向上转换以呈现 IOptions 列表(糟糕!)
  • IOption 公开但不能直接使用(混淆)

关于c# - 是否有更好的设计来公开您不想直接实现的基本接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50472035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com