面向对象的最佳实践 - 继承v组合v接口 [英] Object Oriented Best Practices - Inheritance v Composition v Interfaces

查看:107
本文介绍了面向对象的最佳实践 - 继承v组合v接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一个关于如何处理简单的面向对象设计问题的问题。我对自己处理这种情况的最佳方法有一些想法,但我有兴趣听听Stack Overflow社区的一些意见。还欢迎链接到相关的在线文章。我正在使用C#,但问题不是语言特定的。

I want to ask a question about how you would approach a simple object-oriented design problem. I have a few ideas of my own about what the best way of tackling this scenario, but I would be interested in hearing some opinions from the Stack Overflow community. Links to relevant online articles are also appreciated. I'm using C#, but the question is not language specific.

假设我正在编写一个视频商店应用程序,其数据库有 Person 表, PersonId 名称 DateOfBirth 地址字段。它还有一个 Staff 表,其中包含指向 PersonId 的链接,以及一个客户表格也链接到 PersonId

Suppose I am writing a video store application whose database has a Person table, with PersonId, Name, DateOfBirth and Address fields. It also has a Staff table, which has a link to a PersonId, and a Customer table which also links to PersonId.

一个简单的面向对象的方法是假设 Customer 是一个 Person ,因此创建类似这样的类:

A simple object oriented approach would be to say that a Customer "is a" Person and therefore create classes a bit like this:

class Person {
    public int PersonId { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}

class Customer : Person {
    public int CustomerId { get; set; }
    public DateTime JoinedDate { get; set; }
}

class Staff : Person {
    public int StaffId { get; set; }
    public string JobTitle { get; set; }
}

现在我们可以编写一个函数来向所有客户发送电子邮件:

Now we can write a function say to send emails to all customers:

static void SendEmailToCustomers(IEnumerable<Person> everyone) { 
    foreach(Person p in everyone)
        if(p is Customer)
            SendEmail(p);
}

此系统正常运行,直到我们有一个既是客户又是会员的人工作人员。假设我们不希望我们的每个人列表中有两次同一个人,一次是客户并且一旦作为员工,我们之间做出任意选择:

This system works fine until we have someone who is both a customer and a member of staff. Assuming that we don't really want our everyone list to have the same person in twice, once as a Customer and once as a Staff, do we make an arbitrary choice between:

class StaffCustomer : Customer { ...

class StaffCustomer : Staff { ...

显然只有这两个中的第一个不会破坏 SendEmailToCustomers 函数。

Obviously only the first of these two would not break the SendEmailToCustomers function.

那你会怎么做?


  • 使 Person 类具有对的可选引用StaffDetails CustomerDetails class?

  • 创建一个包含 Person 的新类,以及可选的 StaffDetails 为CustomerDetails

  • 将所有内容设为界面(例如 IPerson IStaff ICustomer )并创建三个实现适当接口的类?

  • 采取另一种完全不同的方法?

  • Make the Person class have optional references to a StaffDetails and CustomerDetails class?
  • Create a new class that contained a Person, plus optional StaffDetails and CustomerDetails?
  • Make everything an interface (e.g. IPerson, IStaff, ICustomer) and create three classes that implemented the appropriate interfaces?
  • Take another completely different approach?

推荐答案

马克,这是一个有趣的问题。你会发现很多意见。我不相信有一个正确的答案。这是一个很好的例子,说明在构建系统之后,刚性的层次对象设计确实会导致问题。

Mark, This is an interesting question. You will find as many opinions on this. I don't believe there is a 'right' answer. This is a great example of where a rigid heirarchial object design can really cause problems after a system is built.

例如,假设你选择了客户, 员工课程。部署系统,一切都很愉快。几个星期后,有人指出他们既是员工又是客户,他们没有收到客户的电子邮件。在这种情况下,您需要进行大量的代码更改(重新设计,而不是重新设计)。

For example, lets say you went with the "Customer" and "Staff" classes. You deploy your system and everything is happy. A few weeks later, someone points out that they are both 'on staff' and a 'customer' and they are not getting customer emails. In this case, you have a lot of code changes to make (re-design, not re-factor).

我认为它过于复杂且难以维护如果您尝试使用一组派生类来实现所有排列以及人员及其角色的组合。鉴于以上示例非常简单,这一点尤其正确 - 在大多数实际应用中,事情会更复杂。

I believe it would be overly complex and difficult to maintain if you attempt to have a set of derived classes that implement all the permutations and combination of people and their roles. This is especially true given that the above example is very simple - in most real applications, things will be more complex.

对于您的示例,我会选择Take另一个完全不同的方法。我将实现Person类,并在其中包含角色的集合。每个人都可以拥有一个或多个角色,例如客户,员工和供应商。

For your example here, I would go with "Take another completely different approach". I would implement the Person class and include in it a collection of "roles". Each person could have one or more roles such as "Customer", "Staff", and "Vendor".

这样可以更轻松地添加角色,因为新要求是发现。例如,您可能只有一个基础角色类,并从中派生新角色。

This will make it easier to add roles as new requirements are discovered. For example, you may simply have a base "Role" class, and derive new roles from them.

这篇关于面向对象的最佳实践 - 继承v组合v接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆