我不知道我应该继承多么严重..
在我的应用程序中,我在大多数应用程序中都有客户,用户和供应商。
好吧,看起来很容易,但要成为细节的坚持者,我应该做到以下几点:class Person {...}
class NaturalPerson extends Person {...}
class JuristicPerson extends Person {...}
class User extends NaturalPerson {...}
class Supplier extends JuristicPerson {...}
嗯,和客户有什么关系?在我看来,他们也可能是自然人和法人......
class JurCustomer extends JuristicPerson {...}
class NatCustomer extends NaturalPerson {...}
如果我想拥有所有客户,我需要选择两个相应的表...
基本上我更喜欢每个类型的模式...但根据上面的层次结构,我认为它可能会变得有点复杂。
嗯,这只是一个例子。在许多情况下,层次结构会更复杂......答案 0 :(得分:1)
这里要考虑的设计模式是:
这是经典的Table-per-Type方法。如果没有物体 - 关系阻抗不匹配,例如,该模式是适用的。当您的表与对象结构1:1匹配时。如果你有关系数据,你必须开始在ActiveRecord上填充ORM功能,这不是模式的用途。因此,当您拥有juristic_customer_table
和juristic_person_table
等等时,请使用此功能。
许多应用中的现实是OO结构与DB结构不匹配,因为两者都解决了结构问题本质上的不同。此外,保持两者分离使得独立开发变得更加容易。因此,DataMapper通常是一个更好的选择。虽然选择更复杂。
引用POEAA:此模式“将继承结构的所有类的所有字段映射到单个表中”。当您提取数据时,您通过Mapper(也处理CRUD)运行记录集,它知道要使用哪些数据实例化哪个类。为了便于使用,该表还可以保存对象的类名。这显然会将您的类的实现细节泄露到数据库中。
根本不要使用继承,而是使用聚合。找到保存数据的基本类。然后制作封装该角色职责的小型Role对象,例如
$supplier = new Supplier(new Juristic(new Person(PersonGateway::findById(1))));
然后,您的供应商将掌握与供应商相关的所有逻辑。在与供应商交互时,您可能不需要Juristic或Person所拥有的任何内容。这应该都是供应商内部的。您的公共供应商界面将以这种方式小得多,并且可以更清晰地分离您的对象可以履行的职责。
这样您就不会创建is-a关系,而是具有-a或uses-a。我假设Juristic拥有某种与您的用例相关的业务逻辑。如果Juristic和Natural之间的唯一区别是语义,那么完全删除它。有关详细信息,请参阅my blog post on Modeling the Real World。
答案 1 :(得分:1)
不必要的抽象层在不提供任何好处的情况下增加了复杂性。
您需要做的是确定从共享共同祖先的类中可以获得哪些实现优势。
我认为设计应用程序的最佳方式可能是从数据库模式开始,该模式准确地表示您正在处理的实体和关系。然后创建您的类以镜像该架构(每种类型的表)。
然后在考虑类似类的功能时,确定不同的类型是否会从共享基类中受益。例如,基于此设计技术,您最终会获得Customer和Supplier类。部分要求规定您需要一种获取信息以打印邮件标签的方法。如果您为获得此信息而进行的过程是相同的,那么在抽象类中进行设计是有意义的,然后两者都会扩展以实现该方法。
这有助于在设计应用时管理复制粘贴编码。