如何使用存储库模式和工厂方法模式组织我的类/接口?

发布于 2024-08-06 06:08:45 字数 1223 浏览 6 评论 0原文

我正在创建一个示例应用程序来一起理解存储库和工厂方法模式,因为将在更大的项目中使用。

我想要实现的是能够使网站与不同的 ORM 工具一起工作。

例如,网站将实现 LINQ to SQL 和 Ado 实体框架工作类,然后使用工厂方法将使用这些 ORM 之一“使用配置值”来加载存储库对象中的数据。

到目前为止我得到的内容如下

interface IRepository : IDisposable
{
  IQueryable GetAll();  
}

interface ICustomer : IRepository
{
}

public class CustomerLINQRepository : ICustomer
{
    public IQueryable GetAll()
    {
       // get all implementation using linqToSql
    }
    public void Dispose()
    {
      throw;
    }
    public IRepository GetObject()
    {
        return this;
    }
}


public class CustomerADORepository : ICustomer
{
    public IQueryable GetAll()
    {
       // get all implementation using ADO
    }
    public void Dispose()
    {
      throw new NotImplementedException();
    }
    public IRepository GetObject()
    {
        return this;
    }
}


// Filling a grid with data in a page
IRepository customers = GetCustomerObject();
this.GridView1.DataSource = customers.GetAll();
this.GridView1.DataBind();
////

public IRepository GetCustomerObject()
{
    return new CustomerLINQRepository(); // this will return object based on a config value later
}

但我可以感觉到有很多设计错误希望你能帮助我找出来以获得更好的设计。

I am creating a sample, application to understand repository and factory method patterns together, because will use in a bigger project.

What i want to achieve is be able to make the website work with different ORM tools.

For example the website will have LINQ to SQL and Ado entity frame work classes implemented then using the factory method will use one of these ORMs "using config value" to load the data in the repository objects.

What i got till now is like the following

interface IRepository : IDisposable
{
  IQueryable GetAll();  
}

interface ICustomer : IRepository
{
}

public class CustomerLINQRepository : ICustomer
{
    public IQueryable GetAll()
    {
       // get all implementation using linqToSql
    }
    public void Dispose()
    {
      throw;
    }
    public IRepository GetObject()
    {
        return this;
    }
}


public class CustomerADORepository : ICustomer
{
    public IQueryable GetAll()
    {
       // get all implementation using ADO
    }
    public void Dispose()
    {
      throw new NotImplementedException();
    }
    public IRepository GetObject()
    {
        return this;
    }
}


// Filling a grid with data in a page
IRepository customers = GetCustomerObject();
this.GridView1.DataSource = customers.GetAll();
this.GridView1.DataBind();
////

public IRepository GetCustomerObject()
{
    return new CustomerLINQRepository(); // this will return object based on a config value later
}

But i can feel that there are a lot of design mistakes hope you can help me figure it out to get better design.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

红玫瑰 2024-08-13 06:08:45

我的两点意见:

A.我会添加通用基础存储库类。无论类型是什么,许多存储库操作都是相同的。它可以节省您大量的打字时间。

B. 我不明白为什么您的存储库要实现 ICustomer 接口。
数据对象的接口是一个很好的实践,但我认为您的存储库不应该实现它。

C. 如果您的数据对象有一个通用的实现,我将为它们创建一个基类,并限制存储库仅适用于该类型的派生类。

我会做类似的事情:

public interface IEntity
{
     // Common to all Data Objects
}

public interface ICustomer : IEntity
{
     // Specific data for a customer
}


public interface IRepository<T, TID> : IDisposable where T : IEntity
{
     T Get(TID key);
     IList<T> GetAll();
     void Save (T entity);
     T Update (T entity);

     // Common data will be added here
}

public class Repository<T, TID> : IRepository<T, TID>
{
     // Implementation of the generic repository
}

public interface ICustomerRepository
{
     // Specific operations for the customers repository
}

public class CustomerRepository : Repository<ICustomer, int>, ICustomerRepository
{
     // Implementation of the specific customers repository
}

用法:

CustomerRepository repository = new CustomerRepository();
IList<ICustomer> customers = repository.GetAll();
// Do whatever you want with the list of customers

这就是我使用 NHibernate 实现 DAL 的方式。您可以在“NHibernate in Action”中找到该用法的一些变化。

我还建议使用某种 IoC 控制器,正如 Matt 建议的那样。

My two cents:

A. I would add generic base repository class. a lot of the repository actions will be the same no matter what the type is. it can save you lots of typing.

B. I don't understand why your repositories are implementing the ICustomer interface.
an interface for your Data Objects is a good practice but I don't think that your repository should implement it.

C. If there is a common implementation to your Data Objects, I would create a base class for them and restrict the repositories to work only with derived classes of the type.

I would do something like that:

public interface IEntity
{
     // Common to all Data Objects
}

public interface ICustomer : IEntity
{
     // Specific data for a customer
}


public interface IRepository<T, TID> : IDisposable where T : IEntity
{
     T Get(TID key);
     IList<T> GetAll();
     void Save (T entity);
     T Update (T entity);

     // Common data will be added here
}

public class Repository<T, TID> : IRepository<T, TID>
{
     // Implementation of the generic repository
}

public interface ICustomerRepository
{
     // Specific operations for the customers repository
}

public class CustomerRepository : Repository<ICustomer, int>, ICustomerRepository
{
     // Implementation of the specific customers repository
}

Usage:

CustomerRepository repository = new CustomerRepository();
IList<ICustomer> customers = repository.GetAll();
// Do whatever you want with the list of customers

That is the way that I implemented my DAL Using NHibernate. you can find some twists of that usage in "NHibernate in Action".

I would also recommend using some kind of IoC controller as Matt suggested.

独享拥抱 2024-08-13 06:08:45

我不确定 GetWanted 的命名。你到底想要得到什么?名称应该更具描述性,也许是 GetCustomerRepository

GetCustomerObjectGetWanted 相同吗?

抛出有什么用?

I'm not sure on the naming of GetWanted. What exactly is wanted that you are getting? The name should be more descriptive, maybe GetCustomerRepository?

Is GetCustomerObject the same as GetWanted?

What is the throw for?

妄想挽回 2024-08-13 06:08:45

大部分看起来都不错。我有两点意见:

  1. 我不会将您的客户存储库称为 ICustomer。我将其称为 ICustomerRepository。这更加直接,并且澄清了接口基于存储库的职责。 ICustomer 听起来像是封装 Customer 数据的 DataObject。
  2. 考虑使用 IOC 容器(谷歌结构图、温莎城堡或 Unity)而不是使用工厂方法。您最终可能会得到很多工厂方法,这可能会导致混乱。相反,在代码中放置一个位置来让 IOC 连接所有存储库可能会更干净。

Looks good for the most part. I have two comments:

  1. I would not call your customer Repository ICustomer. I would call it ICustomerRepository. That is more straight forward and and clarifies the repository based responsibility of the interface. ICustomer sounds like a DataObject encapsulating Customer data.
  2. Look into using an IOC container (google structure map, castle windsor or unity) instead of using the factory method. You could end up with alot of factory methods which could lead to confusion. Instead, it may be cleaner to have a single place in your code where your IOC wires up all of your repositories.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文