RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1077712
Accepted
Adam Shakhabov
Adam Shakhabov
Asked:2020-02-03 19:11:08 +0000 UTC2020-02-03 19:11:08 +0000 UTC 2020-02-03 19:11:08 +0000 UTC

Null 对象模式的接口或抽象类?

  • 772

我正在开发一个用于使用模式的库,其中域逻辑如下:

  • 有一个计划;
  • 架构可以包含表格或图片,但不能同时包含两种内容。

如果将使用我的库的开发人员尝试访问表 ( Scheme.Table.Rows) 并且架构没有表,那么NullReferenceException我希望抛出一个更容易理解的错误,而不是 。并决定实施该模式Null Object。


界面

现在这是通过界面完成的,这就是它在项目中的外观:

public class Scheme
{
    public ITable Table { get; }
    public IPicture Picture { get; }

    /// <summary>
    /// Creates a new <see cref="Scheme"/> instance with table content.
    /// </summary>
    public Scheme(ITable table)
    {
        Table = table;
        Picture = new NoPicture();
    }

    /// <summary>
    /// Creates a new <see cref="Scheme"/> instance with picture content.
    /// </summary>
    public Scheme(IPicture picture)
    {
        Table = new NoTable();
        Picture = picture;
    }
}

public interface ITable
{
    IEnumerable<Row> Rows { get; }
}

public class Table : ITable
{
    public IEnumerable<Row> Rows { get; }
}

public class NoTable : ITable
{
    public IEnumerable<Row> Rows => throw new Exception("Scheme does not contain a table.");
}

public interface IPicture
{
    Image Image { get; }
}

public class Picture : IPicture
{
    public Image Image { get; }
}

public class NoPicture : IPicture
{
    public Image Image => throw new Exception("Scheme does not contain a picture.");
}

抽象类

下面是它在抽象类上的样子:

public class Scheme
{
    public AbstractTable Table { get; }
    public AbstractPicture Picture { get; }

    /// <summary>
    /// Creates a new <see cref="Scheme"/> instance with table content.
    /// </summary>
    public Scheme(AbstractTable table)
    {
        Table = table;
        Picture = new NoPicture();
    }

    /// <summary>
    /// Creates a new <see cref="Scheme"/> instance with picture content.
    /// </summary>
    public Scheme(AbstractPicture picture)
    {
        Table = new NoTable();
        Picture = picture;
    }
}

public abstract class AbstractTable
{
    public abstract IEnumerable<Row> Rows { get; }
}

public class Table : AbstractTable
{
    public override IEnumerable<Row> Rows { get; }
}

public class NoTable : AbstractTable
{
    public override IEnumerable<Row> Rows => throw new Exception("Scheme does not contain a table.");
}

public abstract class AbstractPicture
{
    public abstract Image Image { get; }
}

public class Picture : AbstractPicture
{
    public override Image Image { get; }
}

public class NoPicture : AbstractPicture
{
    public override Image Image => throw new Exception("Scheme does not contain a picture.");
}

问题

这是可以使用接口或抽象类实现相同事物的另一种情况。但从逻辑和设计的角度来看,哪个更正确?

我通常使用抽象类将公共代码放在单独的位置,最重要的是,实体之间的关系是IS类型,但我发现很难说它是NoTabel什么AbstractTable。

c#
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. ishkin
    2020-02-03T19:40:19Z2020-02-03T19:40:19Z

    我认为接口会更正确,这就是原因。

    接口最初被认为是两个功能对象之间的中间对象。

    发明抽象类是为了通过删除通用属性和方法来减少代码。

    在您的情况下,如果您打算在其他项目中使用它,您可以更轻松地浏览界面。而且会更容易参考,接口上的注释也会更容易阅读。

    • 0
  2. Best Answer
    Vlad
    2020-02-03T21:43:23Z2020-02-03T21:43:23Z

    为了解决这个问题

    如果将使用我的库的开发人员尝试访问一个表 (Scheme.Table.Rows),但该模式没有一个,那么我希望抛出一个更明显的错误,而不是 NullReferenceException。

    你不需要使用模式Null Object。在属性中抛出异常就足够了:

    public class Scheme
    {
        private readonly Table table;
        private readonly Picture picture;
    
        public Table Table => table ?? throw new Exception("Scheme does not contain a table.");
        public Picture Picture => picture ?? throw new Exception("Scheme does not contain a picture.");
    
        // со слов автора, такое свойство имеется
        public bool HasTable => table != null;
    
        public Scheme(Table table)
        {
            this.table = table ?? throw new ArgumentNullException(nameof(table));
        }
    
        public Scheme(Picture picture)
        {
            this.picture = picture ?? throw new ArgumentNullException(nameof(picture));
        }
    }
    
    public class Table
    {
        public override IEnumerable<Row> Rows { get; }
    }
    
    public class Picture
    {
        public override Image Image { get; }
    }
    

    Table如果您需要对and的依赖关系的抽象,请Picture添加接口:

    public class Scheme
    {
        ...
    
        public Scheme(ITable table) { ... }
    
        public Scheme(IPicture picture) { ... }
    }
    
    public interface ITable { ... }
    
    public class Table : ITable { ... }
    
    public interface IPicture { ... }
    
    public class Picture : IPicture { ... }
    

    是否有多种具有通用代码的接口实现?添加一个抽象类:

    public abstract class AbstractTable : ITable { ... }
    
    public class Table : AbstractTable { ... }
    
    public class AbstractPicture : IPicture { ... }
    
    public class Picture : AbstractPicture { ... }
    
    • 0

相关问题

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5