8

我目前有一个完全用程序 PHP 编写的相当大的应用程序。我希望进一步提升我的 PHP 经验,并使用面向对象的技术重新编写我的大部分应用程序。

在很多领域,OOP 可以帮助减少代码量并使其更易于阅读。但是,我有几个问题。

1)我的理解是,一个类被用作任意数量对象的蓝图,但是任何一个类只代表一个对象,从不超过一个。所以一个类可以代表一个玩家,但不能代表多个玩家。

2)由于我将包含很多不同的类,我是使用“加载器”类来加载它们,spl_autoload_register还是只spl_autoload_register在我的应用程序的程序文件中使用?

编辑:所以我的自动加载器将是一个类,然后我创建一个实例来启动自动加载,或者只是一个带有函数和 spl_autoload_register 的 php 文件,我将包括以避免在多个文件中重复相同的代码?

3)我的一些课程依赖于其他课程。我以前从未遇到过这种情况,所以老实说,我不知道答案。如果我在我的主程序文件中包含所有类,但我的播放器类不包含它需要运行的类,那么播放器类是否可以工作,因为主程序已经包含了播放器依赖的类?

编辑:所以即使一个类可以实例化一个 Player 类型的对象,并且 Player 类不直接包含在此类中,它仍然可以工作,因为控制器类确实包含 Player 类?

4)在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的 Player 类中,有时我需要从一个 Player 向另一个 Player 发送一些东西。那么,我是在 Player 类中实现一个以两个 Player 作为参数的静态方法并进行传输还是做其他事情?

编辑:好的,所以避免使用静态方法。现在我遇到了一个严重的问题:我的应用程序中有多次运行的方法,但我无法将它们实现为静态方法。我应该将它们实现为实例方法吗?例如,从一个播放器发送到另一个播放器。我会创建一个实例方法,它接受一个 Player 对象并向它发送发送吗?

5)我有很多方法不属于任何一个类的实例,也不适合作为静态方法。这些是否应该在自己的类中声明为 Common 或类似的静态方法?在这种情况下在实践中做了什么?

编辑:这些方法是否属于使用它们的特定应用程序文件,或者可能存储在它们自己的“functions.php”文件中?

6)我想学习如何使用命名空间,但是我的代码永远不会被其他人使用,我也永远不会在我的应用程序中使用其他人的代码。命名空间是我的应用程序中不必要的添加,还是学习如何使用它们是个好主意?无论如何,一个应用程序有一个命名空间(应用程序名称?)还是每个类都属于它自己的命名空间?

7)最后,有一个用于数据库连接的类和一个用于网络方法的类是否很常见?我的应用程序需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

感谢您提供的任何帮助和见解。

4

3 回答 3

4

1)我的理解是,一个类被用作任意数量对象的蓝图,但是任何一个类只代表一个对象,永远不会超过一个。所以一个类可以代表一个玩家,但不能代表多个玩家。

一个类不代表任何东西,因为正如您正确指出的那样,它只是任意数量对象的蓝图。您可以拥有代表多个玩家的同一类的多个实例(对象)。

2) 由于我将包含很多不同的类,我是使用“加载器”类来使用 spl_autoload_register 加载它们,还是只在我的应用程序的程序文件中使用 spl_autoload_register?

在不知道“我的应用程序的程序文件”是什么意思的情况下,我说是的。使用自动加载器,因为它可以正常工作,而您不必担心会做require_*.

3)我的一些课程依赖于其他课程。我以前从未遇到过这种情况,所以老实说,我不知道答案。如果我在我的主程序文件中包含所有类,但我的播放器类不包含它需要运行的类,那么播放器类是否可以工作,因为主程序已经包含了播放器依赖的类?

您不想加载所有类,而只想加载您将要使用的类。使用自动装载机时,这又不是您必须担心的事情。但是是的,一旦加载了一个类,它就可以在整个应用程序中实例化。

通常您会希望在应用程序的引导阶段启动 autploader 。

4) 在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的 Player 类中,有时我需要从一个 Player 向另一个 Player 发送一些东西。那么,我是在 Player 类中实现一个将两个 Player 作为参数的静态方法并进行传输还是做其他事情?

避免在 OOP PHP 中使用静态方法。几乎从不需要它。你可以考虑拥有另一个类,它就像一个玩家池,负责从一个玩家到另一个玩家“发送数据”。

因此,只要它在尝试实例化它之前发生,包含该类的文件的位置并不重要。

5)我有很多方法不属于任何一个类的实例,也不适合作为静态方法。这些是否应该在自己的类中声明为 Common 或类似的静态方法?在这种情况下在实践中做了什么?

再次请不要使用静态方法。如果你在其他类中使用它们,你只会让你的类难以进行单元测试,并且你会引入隐藏的依赖关系。以我的经验,它几乎从来没有碰巧在某处有一个单一的方法。也许你的方法做得太多了。

但这很难仅通过阅读您的问题来判断。也许你可以在评论中举个例子?

6)我想学习如何使用命名空间,但是我的代码永远不会被其他人使用,我也永远不会在我的应用程序中使用其他人的代码。命名空间是我的应用程序中不必要的添加,还是学习如何使用它们是个好主意?

PHP 中的命名空间是关于结构化的。尽管没有其他人会使用您的代码,但您不必担心在某处为某个类使用相同的名称。一旦应用程序变大而不是迟到,就会发生这种情况。

无论如何,一个应用程序有一个命名空间(应用程序名称?)还是每个类都属于它自己的命名空间?

在命名空间方面,我经常遵循PSR-0

7)最后,有一个用于数据库连接的类和一个用于网络方法的类是否很常见?我的应用程序需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

只需牢记单一职责原则,并且通常是SOLID

另外,我强烈建议您观看这些内容并继续观看,直到您理解为止。

于 2013-03-14T22:30:53.173 回答
2

1)我的理解是,一个类被用作任意数量对象的蓝图,但是任何一个类只代表一个对象,永远不会超过一个。所以一个类可以代表一个玩家,但不能代表多个玩家。

通常,您还将拥有表示对象集合的类,例如可用于从所有玩家的集合中检索单个玩家的“玩家”类:

$players = new Players();
$john = $players->findByName("john");

2) 由于我将包含很多不同的类,我是使用“加载器”类来使用 spl_autoload_register 加载它们,还是只在我的应用程序的程序文件中使用 spl_autoload_register?

这在很大程度上取决于您的项目的复杂性。一个简单的自动加载器函数通常就足够了,但您可以看看Zend Framework Autoloader 类

3)我的一些课程依赖于其他课程。我以前从未遇到过这种情况,所以老实说,我不知道答案。如果我在我的主程序文件中包含所有类,但我的播放器类不包含它需要运行的类,那么播放器类是否可以工作,因为主程序已经包含了播放器依赖的类?

是的。但是,通过自动加载,您根本不需要担心这一点。如果不使用自动加载,最好在定义类的文件中包含所需的类(使用require_once()以避免多次包含同一个文件)。

4) 在多种情况下,我需要处理我正在创建的对象。我想知道我应该怎么做。例如,在我的 Player 类中,有时我需要从一个 Player 向另一个 Player 发送一些东西。那么,我是在 Player 类中实现一个将两个 Player 作为参数的静态方法并进行传输还是做其他事情?

静态方法几乎总是错误的方法。普通方法属于一个实例(即特定的播放器),静态方法属于类,即播放器的一般“想法”。如果您需要将内容从一个播放器转移到另一个播放器,为什么不这样实现:

class Player {
    public function transferMoney(Player $recipient, $amount) { ... }
}

$tom = new Player("tom");
$marc = new Player("marc");

$tom->transferMoney($marc, 500);

5)我有很多方法不属于任何一个类的实例,也不适合作为静态方法。这些是否应该在自己的类中声明为 Common 或类似的静态方法?在这种情况下在实践中做了什么?

我无法合理地回答这个问题。然而,PHP 中仍然有一些普通函数,这似乎是这种情况下的最佳方法。然而,如果你正确地使用 OOP,你很可能永远不会遇到这样的问题。这通常是您的类设计的问题,这使您认为这些方法不属于任何对象。

6)我想学习如何使用命名空间,但是我的代码永远不会被其他人使用,我也永远不会在我的应用程序中使用其他人的代码。命名空间是我的应用程序中不必要的添加,还是学习如何使用它们是个好主意?无论如何,一个应用程序有一个命名空间(应用程序名称?)还是每个类都属于它自己的命名空间?

命名空间很棒,但没有它们你的代码可能会很好。由于命名空间可以嵌套,您通常会有一个顶级命名空间和每个组件的子命名空间。

7)最后,有一个用于数据库连接的类和一个用于网络方法的类是否很常见?我的应用程序需要两者。我认为将代码转换为使用面向对象技术时遇到的主要问题是确定将哪些方法放在哪里,因为目前它们都在一个整体文件中。

这取决于您如何模拟您的实际情况。如果数据库连接和“网络”对您来说是两个不同的东西,那么两个类是要走的路。

于 2013-03-14T22:33:08.700 回答
1
  1. APlayerCollection将是一个有效的类。当然,它的一个对象是多个玩家的一个集合。

  2. 使用 spl_autoload_register,句号。最好遵循PSR-0标准并使用任何符合 PSR-0 的现有自动加载器(即Symfony Loader

  3. 它会起作用的。但是由于您使用自动加载器(请参阅 2。)您根本不必关心包含类

  4. 从玩家 1 向玩家 2 发送消息很容易翻译为在玩家 1 中调用玩家 2 的方法。但是,“发送东西”和“处理对象”可能意味着很多东西,所以答案是:视情况而定。但总的来说,避免使用静态方法是个好建议。

  5. 这听起来很像程序性思维。很抱歉,我不能在这里给你一个灵丹妙药的答案,你必须学习和理解面向对象设计的原则才能应用它们。网络上有一些标准文献和许多有用的资源。通过示例学习也可能很有用(查看其他开源的 OO 应用程序和框架)

  6. “一个应用程序有一个命名空间(应用程序名称?)还是每个类都属于它自己的命名空间?” - 答案介于两者之间。命名空间可用于将一起工作的事物组合在一起,并且无论谁使用或查看代码,它们都很有用。

  7. 面向对象设计的第一条规则:一个类,一个责任。

于 2013-03-14T22:31:54.267 回答