php - 为对象交互设计类和函数

标签 php oop class design-patterns object

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。




9年前关闭。




我一直在尝试学习 OOP 技术和设计模式一段时间,我的方法确实有所改进,但是当我们谈论不同类的对象交互时,我并没有完全点击。我主要使用 PHP 工作,但为了学习,我会接受一般性的答案。如果我使用错误的术语,请提前道歉,我在这里自学。下面是一个例子:

假设我想模拟人们开车四处走动。有3个类:

class Car {}
class Driver {}
class Road {}

我希望 Car 类有一个功能
public function Drive($time) {}

因此,驾驶应根据道路的速度限制更新驾驶员的位置。我的问题是构建 Drive 以便 Car 与其他对象交互的最佳方式是什么。我可以从头顶上看到 3 种可能性:
public function Drive($time, $Driver, $Road) {}

这里的优点是函数本身会告诉我我需要什么参数。缺点是如果我有很多类似的操作,一路上调用私有(private)函数,添加乘客对象等,我最终可能会传递很多参数。
$Car->setDriver($Driver);
$Car->setRoad($Road);
$Car->Drive($time);

优点是我可以非常简单地调用 Drive 并且它可以访问它需要的任何东西。缺点是我必须记住先设置驱动程序和道路,因为函数定义没有告诉我。
class Car() {
  public function Drive($time) {
    $Driver = getDriver($this->DriverID);
    $Road = getRoad($this->RoadID);
  }
}
function getDriver($DriverID) {
  static $DriverArray;
  // check isset(), create object and place in array if not
  return $DriverArray[$DriverID]; 
}
function getRoad($RoadID) {} // assume similar

优点是所有逻辑都是内部逻辑,DriverID 和 RoadID 存在,因为它们是来自数据库的外键。 (或者它们可以事先手动设置,但这不会是内存问题,因为它是有意分配的。)缺点是所有 Driver 操作都必须通过相同的 getDriver 以免我最终得到单独的实例同一个驱动程序。

为了完整起见,我的第四种方法是 SELECT <columns> FROM Car_tbl INNER JOIN Driver_tbl on DriverID INNER JOIN Road_tbl on RoadID ,我很确定这是糟糕的 OO 设计,但这是我过去所做的,因为它执行的查询较少。

我倾向于方法 3,但怀疑我在很大程度上遗漏了一些东西。随意回答特定于 PHP 的问题或通常是如何考虑的。谢谢。

编辑:感谢到目前为止的答案,包括进一步阅读的链接。
与其让示例过于复杂,不如让我们现在假设最简单的用例,但稍后假设最复杂的用例。所以例如速度是现在getRoadSpeedLimit()的功能, 但后来受 getMaxCarSpeed() 的限制和 getMaxDriverSpeed()汽车需要汽油,司机需要食物。如果我们有太多的 Driver 对象使用同一条道路等,道路的速度限制会调整。

Gordon 和 UmlCat 似乎都在插入(可以这么说)使用封装类,对吗?
class RoadTrip_aka_Universe {
  // Operates on instances of Car, Driver, Route (which may contain roads)
}

但这是否仍然留下了问题,是否在构造函数中添加了 $Car、$Driver 和 $Route,由 setter 应用,从静态外部引入?无论我们决定哪个类应该有方法,它如何访问那些其他对象?

另外我的直觉 react 是,如果一切都在一个更大的类中进行,那么该类的内部是不是开始类似于具有全局变量的大型无类结构?不要将其视为批评,我只是想了解一下,因为它感觉像是 OOP 的文字,而不是它的精神。

再次,谢谢。

最佳答案

首先,虽然似乎没有必要,您可以添加一个包含所有其他对象的类,例如“宇宙”或“世界”。这将帮助您将现实世界建模为应用程序。

class CarClass
{

} // class CarClass

class DriverClass
{

} // class DriverClass

class RoadClass
{

} // class RoadClass

class WorldClass
{
  /* public CarClass */ $Car;
  /* public DriverClass */ $Driver;
  /* public RoadClass */ $Road;
} // class WorldClass

并且,一个小代码示例。可能是这样的:
 /* void */ function Example()
 {
    WorldClass $MyWorld = new WorldClass();

    // ...
 } // void function Example

下一个。每个对象的“字段”、“操作”、“成员”是什么?
你提到,“限速”取决于道路。
class RoadClass
{
   /* public int */ $SpeedLimit; 
} // class RoadClass

/* void */ function Example()
{
   WorldClass $MyWorld = new WorldClass();

   $MyWorld->Road->SpeedLimit = "50" // ouch, "cow country"
    // ...
} // void function Example

对象如何交互。那么,这里有一个问题。有时对象依赖于他人,就像成为他人的一部分一样,有时,对象是独立的,它们只是相关的。

在这个例子中,大多数对象都依赖于“世界”对象,但是,它们只是相互关联。让我们添加一个小注释来检查一下。
class WorldClass
{
  /* public depends CarClass */ $Car;
  /* public depends DriverClass */ $Driver;
  /* public depends RoadClass */ $Road;

  function __construct() {
     // parent::__construct();

     // "World" "contains" these objects
     $this->Car = new CarClass();
     $this->Driver = new DriverClass();
     $this->Road = new RoadClass();
  } // function __construct()

} // class WorldClass

汽车有一个记录机,记录移动了多少距离,如果启动、移动和停止。它是一个简单的值,而不是一个对象。
class CarClass
{
   /* public int */ $Distance; 
} // class RoadClass

但是,存在与“外部”对象的交互:
class CarClass
{
   /* public int */ $Distance; 
   /* public DriverClass related */ $Driver; 
   /* public RoadClass related */ $Road; 


  function __construct() {
     // parent::__construct();

     // "Car" only relates these objects
     $this->Driver = null;
     $this->Road = null;
  } // function __construct()
} // class RoadClass

/* void */ function Example()
{
   WorldClass $MyWorld = new WorldClass();
   $MyWorld->Road->SpeedLimit = "50"; // ouch, "cow country"

   $MyWorld->Car->Road = $MyWorld->Road; // a reference only
   $MyWorld->Car->Driver = $MyWorld->Driver; // a reference only

    // ...
} // void function Example

由于汽车的距离取决于道路限速,并且会发生变化,因此当汽车行驶时:
class CarClass
{
   /* public int */ $Distance; 
   /* public DriverClass related */ $Driver; 
   /* public RoadClass related */ $Road; 

  function __construct() {
     // parent::__construct();

     // "Car" only relates these objects
     $this->Driver = null;
     $this->Road = null;
  } // function __construct()


  /* void */ function Drive($time) {

    // general idea of formula:

    $this->distance = ($this->SpeedLimit * $time * $this->Road->SpeedLimit);
  } // void function Drive(...)

} // class RoadClass

/* void */ function Example()
{
   WorldClass $MyWorld = new WorldClass();
   MyWorld->Road->SpeedLimit = "50"; // ouch, "cow country"

   $MyWorld->Car->Road = $MyWorld->Road; // a reference only
   $MyWorld->Car->Driver = $MyWorld->Driver; // a reference only

   /* int */ $time = 60; // 1 hours in minutes

   $MyWorld->Car->Drive($time);
} // void function Example

干杯。

关于php - 为对象交互设计类和函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9142459/

相关文章:

php - 寄存器上的 Laravel 5.5 条件重定向

javascript - 我可以创建一个隐式转换为数字的 JavaScript 对象吗?

c++ - 类设计建议 : extending a class and code reuse

python - 为什么 Python 深受动画行业从业人员的喜爱?

java - 模块故障

php - 动态更改表格中的行字体颜色

php - 拉拉维尔 5.4 : controller method is called twice on a redirect to it

c++ - 是否可以从派生类向基类 A 添加类成员?

php - 使用 Spout 写入从 Excel 读取的数据失败

C++:类 - 重载构造函数 - 单变量?