在我看来,最好为每个类创建一个文件,其中文件以该类的名字命名。我使用与乍得桦树略有不同的符号,即Classname.class.php
。类自动加载是一个很好的功能,但我不经常使用它(只有在某些情况下,如MVC,经常添加或删除相同类型的类)。
关于对象建模:开始为名词创建类。确定应用程序中的角色。这样做的一个方法是记下你的应用程序应该做什么,然后扫描它的名词并在这些之后为你的类建模。因为一个类代表一个单独的对象,所以大部分时候类名都是单数。如果有多个对象,你应该把它命名为ObjectCollection或类似的东西(例如“BookCollection”)。
让我们试试吧:
我想创建一个小本子库的应用程序来跟踪我的藏书。它应该跟踪我拥有的书籍,流派,作者和我借给他们的朋友。另外,对于每个朋友都应该存储电话号码,所以我可以给他打电话。所有的信息都存储在数据库中。
Book
:代表一本书( “教父”, “Cryptonomicon”)
Library
:代表书籍 集合
Collection
:已经涵盖图书
Genre
(“Sci- “”恐怖片“,”...“)
Author
(”Neal Stephenson“,”Mario Puzo“)
Friend
( “乔”, “吉尔”, “杰克”)
PhoneNumber
(朋友的属性)
Database
(杜)
然后你建立层次结构。哪些对象包含其他对象,它们之间的关系是怎样的?
Library
包含0,1或更多Book
小号
- 甲
Book
属于一个Genre
- 甲
Book
被1个或多个Author
小号
- 我可以借一
Book
为0或1写入Friend
并且一次只有一个Friend
- A
Friend
有一个PhoneNumber
(这也会告诉你一两件关于你的数据库应该如何)。
并非一切都很明显。你真的需要电话号码课吗?这只是一个字符串。在这种情况下,你应该把它变成财产。此外,电话号码并不是真的在Friend对象之间共享的(如果有几个朋友住在一起,并且它们经常改变,但是现在这会有点矫枉过正)。如果名词可以用一个标量值(一个字符串,整数,浮点数)表示,并且没有其他值连接到它们,那么创建类可能会过度。
因此,随着时间的推移,你扩展你的应用程序。你决定不仅存储电话号码,而且还存储地址。地址和电话号码是非常相似的信息类型,因此您可以为街道,城市,邮政编码等添加其他变量。在某个时候,你会感到沮丧,因为Friend
类增长巨大,有很多属性,getters-和setters-方法,其中一些前缀将它们组合在一起(Friend->addressStreet
,Friend>addressPostCode
等)。因此,您可能决定将其重新定位到自己的类,称为Address
(如果您将电话号码保留为Friend
)或Contact
,只是为了保持代码清洁(没有错误,但要小心)。
类层次结构和对象层次结构如何?不要混淆它们,它们是完全不同的东西!如果类似的类共享某些属性,但是在其他属性上不同,则会出现类层次结构。因此,您可以使用它们共享的属性和方法以及继承父级的属性和方法的子类创建一个类,并添加它们自己来处理差异。
在我们的图书馆例子中,那可能是什么?说实话,除了一件有点无意义的事情之外,我想不出任何东西,但我们不妨去想它... Friend
s和Author
s都是Person
s!都有姓名,电话号码和地址。但他们也不同,因为作者写书和朋友不写(作者通常不借你的书)。因此,您可能会定义和Address
- Person
类中的对象,但getUnreturnedBooks()
明确属于Friend
,而getBooksWritten()
属于Author
。
它没有意义,因为你永远不会在同一运行中处理Author
s和Friend
s。但让我们说你需要存储在你的图书馆中的所有地址列表,你可以循环你的收藏人员,并致电getAddress()
。说实话,即使PHP是一个不好的例子,因为你可以将任何你想要的类型一起存储在一个数组中,并以任何你想要的方式访问它们,但是在强类型语言中是不可能的。在Java中,你必须为一个数组定义一个数据类型,如果它们有一个公共继承(但你仅限于原始类的方法),则可以存储不同的类型。足够的那个类继承巫术。
对象层次结构只是说明哪些对象应该包含其他对象。 A library
包含book
对象。 A book
包含一个author
对象。
的其他建议:
尝试是描述性的。不要使用像Library->retrieveValues()
这样的名称,将它命名为Library->getBooks()
,因为Book
对象就是您所得到的。
有时最好在数据类型返回后命名方法。如果他们返回布尔值,这很常见。良好的命名约定可能是has
或is
,如Friend->hasBook($book)
或Book->isInLibraryCurrently()
。
对于某个类的所有对象来说总是相同的值可能是类常量。比方说,如果一个Person
可以是男性或女性,并且您将其存储为数据库中的“m”或“f”,则可以定义类常量Person::GENDER_MALE = 'm'
和Person::GENDER_FEMALE = 'f'
,因此您没有“m”s和“f”分散在你遍历的SQL查询中。
只生成单个实例的类可以建模为单例。一个很好的例子可能是数据库类 - 它不太可能需要一次打开多个事务。阅读更多关于维基百科的单身人士(http://en.wikipedia.org/wiki/Singleton_pattern),但可能有点早。
更新:有些人认为单身人士一个坏主意,因为他们或多或少“刻在石头上,”一旦他们实现这种方式。因此,如果您将Database类作为单例建模,但后来决定需要多个数据库连接(不太可能,但可能),则会出现问题。如果你冒险,单身人士可能会很方便。
类和逻辑是分开的吗?你什么意思? – 2009-04-17 09:30:46