为什么我们的项目需要接口层/抽象类?

时间:2012-03-14 12:31:24

标签: c# asp.net asp.net-mvc asp.net-mvc-3 c#-4.0

我们通常在项目中使用抽象函数/接口。为什么真的需要它?为什么我们不能只去商业逻辑层,数据访问层和表示层

演示层中的功能:

abc();

业务逻辑层中的功能:

 public void abc()
    {
      //Preparing the list
    }

数据访问层中的功能:

public abstract void abc();

数据访问SQLServer层中的功能:

 public override void abc()
    {
       //Connection with database
    }

问题是:为什么需要数据访问层?

8 个答案:

答案 0 :(得分:2)

理解这一点的最简单方法是imo,它是对DataLayer的抽象。

您已设置了从xml文件中检索数据的功能。但是有一天你的产品会缩小,xml就像数据存储一样。所以你传递给一些嵌入式数据库:sqlite。但有一天,您需要在某些企业环境中重用您的库。所以现在您需要开发sqlserveroraclewebservice的访问权限....在所有这些更改中,您需要更改不仅代码实际上访问数据,但实际消费的代码也是如此。多年来您在客户端上首次使用xml数据访问并且对它感到满意的代码呢?反向兼容性怎么样?

如果没有直接解决大部分问题,那么抽象可以解决大部分问题,但绝对会使你的应用程序变得可扩展,并且对变化更具抵抗力,在我们的世界中,有时过于频繁地发生。

答案 1 :(得分:2)

通常,如果在代码中使用接口,那么您将以依赖注入的形式获得代码可操作性。

这将帮助您在某些情况下替换部分实现,例如在单元测试期间提供Mock对象。

答案 2 :(得分:1)

为什么接口:  您是否曾在c#中使用使用:     使用(表格f =新表格())     {     }

在这里,您将看到只能使用实现IDisposable接口的使用中的那些类。

彼此不了解的两件事只能使用Interfaces相互交互。 接口保证“某些”功能肯定是通过这种类型实现的。

为什么分层:

这样你就可以拥有单独的dll,它们可以让你在不同的应用程序中重用。

基本上所有这些都用于代码重用和性能提升。

答案 3 :(得分:0)

我认为你在谈论Facade层。

这是一个可选图层,它将简化业务层的功能。让我们想象一下,你有一个ProductManager和CategoryManager,你想做一个涉及使用两者的特定动作(例如,让我在所有类别中获得前5个产品)然后你可以使用一个使用ProductManager和CategoryManager的外观层。

灵感来自Facade Pattern

答案 4 :(得分:0)

抽象有助于创建功能,无论是通过基类,接口还是组合,如果使用得当,都会对维护,可读性和代码的可重用性产生奇迹。

关于问题中发布的代码,标记为“数据访问层”的代码充当业务层要使用的通用抽象。通过这样做,DAL的特定实现(例如样本中“数据访问SQLServer层”下的内容)与业务层分离。现在,您可以实现访问不同数据库的DAL,或者可能自动提供数据以进行测试等。

存储库模式是在DAL中工作的一个很好的例子(示例简化):

public interface IProductRepository
{
    Product Get(int id);
    ...
}

public class SqlProductRepository : IProductRepository
{

    public Product Get(int id) { ... }
    ...
}

public class MockProductRepository : IProductRepository
{
    private IDictionary<int, Product> _products = new Dictionary<int, Product>()
    {
        { 1, new Product() { Name = "MyItem" } }
    };

    public Product Get(int id) { return _products[id]; }
    ...
}

public class AwesomeBusinessLogic
{
    private IProductRepository _repository;

    public AwesomeBusinessLogic(IProductRepository repository)
    {
        _repository = repository;
    }

    public Product GetOneProduct()
    {
        return _repository.GetProduct(1);
    }
}

尽管此示例使用接口,但同样适用于基类的使用。美妙的是,现在我可以将SqlProductRepositoryMockProductRepository提供给AwesomeBusinessLogic,而则无需更改AwesomeBusinessLogic 的任何内容。如果出现另一个案例,那么所需要的只是IProductRepository的新实现,而AwesomeBusinessLogic仍将处理它而不进行更改,因为它只通过接口访问存储库。

答案 5 :(得分:0)

所有以前的答案都可以解释抽象图层的需求,但我仍然想补充一些想法。

让我们说在我们的项目中,我们在每一层中只有一个服务实现。例如,我有一个联系人DAL和一个联系BLL服务,我们可以做这样的事情

namespace Stackoverflow
{
    public class ContactDbService
    {
        public Contact GetContactByID(Guid contactID)
        {
            //Fetch a contact from DB
        }
    }
}

联系BLL服务:

namespace Stackoverflow
{
    public class ContactBLLService
    {
        private ContactDbService _dbService;
        public ContactBLLService()
        {
            _dbService = new ContactDbService();
        }

        public bool CheckValidContact(Guid contactID)
        {
            var contact = _dbService.GetContactByID(contactID);

            return contact.Age > 50;

        }
    }
}

没有定义接口/抽象类。

如果我们这样做,会有一些明显的缺点。

  1. 代码沟通: 想象一下,如果您的项目涉及,您的服务可能有许多不同的方法,维护者(除了您)如何知道您的服务是做什么的?他是否必须阅读您的整个服务才能修复像InvalidCastOperation这样的小错误? 通过查看界面,人们可以直接了解服务的功能(至少)。
  2. 单元测试

    您可以使用假/模拟服务测试您的逻辑,以提前检测错误,并防止以后发生回归错误。

  3. 更容易更改:

    通过仅通过其他类中的接口/抽象类进行引用,您可以在不需要太多工作的情况下轻松替换这些接口实现。

答案 6 :(得分:0)

抽象类或接口实际上不是一个单独的层 - 它应该是业务逻辑层的一部分,它定义了实际数据访问层(例如SQL数据存储库)需要实现以提供数据的接口访问您的业务层的服务。

如果没有此接口,您的业务层将直接依赖于SQL层,而接口将删除此依赖关系:您将抽象类或接口放入业务逻辑层。然后SQL层(例如,单独的程序集)实现抽象类/接口。这样,SQL层依赖于业务层,而不是相反。

结果是一个灵活的应用程序,具有可以与多个数据存储库一起使用的独立业务层 - 它所需要的只是一个实现业务层定义的接口的层。它实际上并不只是关于数据存储库 - 您的业务层不应该依赖于上下文(asp.net与控制台应用程序与服务等),它不应该依赖于用户界面类,模块接口与您的业务应用程序等。

答案 7 :(得分:0)

抽象使您可以快速进行重构。想想使用其他提供程序而不是使用SQL服务器;如果你没有数据访问层,那么你要做一个巨大的重构,因为你直接调用数据访问方法。但是,如果您有数据访问层,则只需编写一个新的数据访问层,继承自抽象数据访问层,并且不会更改业务层中的任何内容。