我想写一些继承3层结构中的类的东西。这样的抽象例子。
couriers_list -> Courier -> courier_name
class couriers_list {
// I'm searches courier_name of the database and reference to the class of courier_name found in database
public function show_courier() {
return $this->xxx();
}
}
class courier extends couriers_list {
// Function for the courier
// Probably it would interface or abstraction
}
class courier_name extends courier {
// Methods of accurately courier eg. Calculation associated with the delivery
// Here each courier would separate file php eg. ups.php
public function xxx() {
return 'xxx';
}
}
$k = new couriers_list();
echo $k->xxx();
我不认为我可以扩展courier到courier_list,因为我没有访问方法的后代。从外部看,我只想引用类couriers_list,她必须从数据库中获取信息并获取courier_name产生的方法。
如何把这个问题放到组织对象上?
你的类courier应该是一个接口,因为它用来定义你的courier应该如何使用
interface CourrierInterface
{
const CLASS_NAME = __CLASS__;
public function getName();
public function getPrices();
public function XXX();
public function calculateDelivery($from, $to);
/** these are just example add here all the method that define a courier */
}
那么对于你拥有的每个信使,你应该实现de CourrierInterface
class UpsCourrier implements CourrierInterface
{
private $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function XXX()
{
// do something
}
}
我不认为CourrierList应该知道数据库,但只需要包含所有的快递对象你有。这里我使用项目
https://github.com/yvoyer/collection
为了管理集合(TypedCollection类),它允许控制你想在集合中使用的类的类型(这里是courrierInterface),但是如果你想让它更简单,你可以使用数组。
我创建了两个XXX方法,一个用于特定的快递员(因为它是一个列表),另一个用于应用于所有列表。我不知道你需要什么,所以拿走你需要的
class CourrierList
{
/**
* TypedCollection
*/
private $courrierList;
public function __construct()
{
// i prefer to use a collection class that valid my type instead of an array, your choice!
$this->courrierList = new TypedCollection("CourrierInterface");
}
public function addCourrier(CourrierInterface $courrier)
{
$this->courrierList->add($courrier);
}
public function removeCourrier(CourrierInterface $courrier)
{
$this->courrierList->removeElement($courrier);
}
protected function getCourrierByName($courrierName)
{
$closure = function (CourrierInterface $courrier) use ($courrierName) {
return $courrier->getName() == $courrierName;
};
return $this->courrierList->filter($closure)->toArray();
}
// since its a list, you must be able to select your courrier to execute the XXX() method
public function XXXByName($name)
{
$courrier = $this->getCourrierByName($name);
$courrier->XXX();
}
// if you prefer to apply to all your courrierList just do
public function XXX()
{
foreach ($this->courrierList as $courrier) {
$courrier->XXX();
}
}
}
因为我不认为CourrierList应该知道数据库,你可以创建一个工厂,在你的数据库中获取数据,并创建所有的快递。这里dbConnection是你的选择,pdo等等…我只是做了一个例子,找到一个好的方法来查询。
class CourrierListFactory
{
private $dbConnection;
public function __construct(DbConnection $connection)
{
$this->dbConnection = $connection;
}
public function createCourrierList()
{
$results = $this->dbConnection->query(".....")->getResults();
$courrierList = new CourrierList();
foreach ($results as $result) {
$courrier = null;
switch ($result['name']) {
case 'ups':
$courrier = new UpsCourrier();
break;
case 'fedex':
$courrier = new FedexCourrier();
break;
/** and so on ... */
default:
// maybe throw exception if courier is not handle
}
$courrier->setName("....");
/** prepare your object here */
// add the courrier to the list
$courrierList->addCourrier($courrier);
}
return $courrierList;
}
}
最后是如何使用所有这些,首先创建一个dbCOnnection,然后构建你的列表,然后你可以访问
$dbConnection = new DbConnection();
// the factory allows you to separate the database from the List class and may be to generate
// your list in an other way later (using apis, etc...)
$factory = new CourrierListFactory($dbConnection);
$courrierList = $factory->createCourrierList();
$courrierList->XXX(); // apply to all
$courrierList->XXXByName("ups"); // apply just to ups courrier