2015-03-27 3 views
0

Я использую PHP 5.3. У меня есть класс Vehicle. Эти классы унаследовали от Vehicle: Car, SUV, Lorry.Проблема с дизайном PHP/OOP, что является лучшей практикой?

Мне нужно получить массив, содержащий объекты определенного типа, унаследованные от Vehicle. Это может быть массив автомобилей, внедорожников и т. Д.

Как я решил, я создал класс CarCollection со статическим методом, который возвращает список автомобилей. Затем класс под названием SUVCollection для SUV ...

Но если бы я должен был добавить новый класс автомобиля (назовем его самолетом), тогда мне нужно будет создать новый класс AirPlaneCollection. Это плохой выбор?

Цель: Я ищу способ реализации этого, используя только один класс, VehicleCollection возвращает список автомобилей, внедорожников и т.д.

Как я могу знать в коде, что в данном конкретном скрипте VehicleCollection :: getVehicles() вернет автомобили, а не внедорожник? Возможно, у меня может быть какая-то логика проверки класса с того места, где она была вызвана, или я отправляю объект-вызывающий объект в качестве параметра, а затем проверяю, какой класс он есть, и в соответствии с этим получите VehicleCollection :: getVehicles(), чтобы вернуться на внешний вид SUV, а не Автомобиль.

+0

не создаются специализированные классы коллекций, но только один, использующий базовый класс автомобиля.Все остальное - вопрос о геттерах и сеттерах. Другие языки предлагают шаблонные классы или шаблоны классов для такого материала, php не имеет такой вещи. Но опять же вам это не понадобится в ситуации, когда вы хотите использовать php. – arkascha

+2

Вы можете хранить массивы, содержащие экземпляры разных типов, каждый из которых наследуется от «Vehicle». – halfer

+0

Я думаю, что здесь вам нужно использовать инъекцию зависимости - образец дизайна. Может быть, это решит вашу проблему. –

ответ

0

насчет статического свойства в классе Vehicle родительским, что будет выглядеть примерно так:

array('cars' => array(car instances), 
    'suvs' =>array(suv instances). 
    .... 
) 

Тогда вы должны поставить логику в своих конструкторах и деструкторов добавлять и удалять объекты из этого массива ,

Затем вы можете получить список всех автомобилей, позвонив по телефону Vehicle::thatArry['cars']. Но, конечно же, вы хотите бросить несколько хороших геттеров и сеттеров вокруг этого массива.

Я еще не думал об этом, возможно, вам потребуются некоторые настройки. Но если это полностью, холла на меня.

1

Вы можете попробовать создать свой собственный тип коллекции, который подтверждает, что все это транспортное средство, но также обеспечивает, чтобы все они были одним и тем же типом транспортного средства.

<?php 
class Vehicle {} 

class Car extends Vehicle {} 

class SUV extends Vehicle {} 

// This doesn't need to be an SplDoublyLinkedList, it's just 
// a convenient datastructure to demo with 
class VehicleCollection extends SplDoublyLinkedList 
{ 
    public function add($index, Vehicle $obj) 
    { 
     $this->validateType($obj); 
     parent::add($index, $obj); 
    } 

    public function push(Vehicle $obj) 
    { 
     $this->validateType($obj); 
     parent::push($obj); 
    } 

    protected function validateType($obj) 
    { 
     // If we have anything in here, ensure next is the same vehicle type 
     if (!($this->isEmpty() || $this->top() instanceof $obj)) { 
      throw new InvalidArgumentException('Argument passed to ' . __CLASS__ . '::' . __FUNCTION__ . ' must all be instances of same type.'); 
     } 
    } 
} 

// Make a new collection 
$col = new VehicleCollection(); 

// Let's have a couple cars 
$car = new Car; 
$car2 = new Car; 

// And an SUV 
$suv = new SUV; 

// Let's add our cars 
$col->push($car); 
$col->push($car2); 

var_dump($col); 
/* Collection right now: 
class VehicleCollection#1 (2) { 
    private $flags => 
    int(0) 
    private $dllist => 
    array(2) { 
    [0] => 
    class Car#2 (0) { 
    } 
    [1] => 
    class Car#3 (0) { 
    } 
    } 
} 
*/ 

// Now we try to add an SUV 
$col->push($suv); 

// and get this: 
// PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Argument passed to VehicleCollection::validateType must all be instances of same type.' 

Это имеет дополнительное преимущество, которое, если продолжить, например, сделал class SportsCar extends Car {}, что SportsCar мог зайти в вашу коллекцию.

Было указано, что я, возможно, неправильно истолковал ваш вопрос. Если вы просто пытаетесь фильтровать массив, это становится гораздо более простой проблемой. Я бы не стал даже реализовать специальный класс, если это так - просто передать Замыкание в array_filter, что вполне читаемый и простой шаблон, чтобы следовать в другом месте:

$vehicles = [$car, $suv, $car2]; 
$cars = array_filter($vehicles, function($vehicle) { return $vehicle instanceof Car; }); 
$suvs = array_filter($vehicles, function($vehicle) { return $vehicle instanceof SUV; }); 

Таким образом, в этом примере, массив у транспортных средств есть внедорожник, и после фильтрования в массиве $ cars есть только автомобили. Если вы хотите, чтобы сделать этот метод класса, вы могли бы сделать что-то вдоль линий:

public function getAllOfType($type) 
{ 
    return array_filter(
     $this->vehicles, 
     function($vehicle) { return is_a($vehicle, $type); } 
    ); 
} 

Тогда, чтобы захватить только автомобили из вашей коллекции:

$cars = $myVehicleCollection->getAllOfType('Car'); 
+0

Настоящий isue здесь, что OP хочет получить ограниченный набор элементов, например '$ collection-> getPlains()' – DarkBee

+0

Хмм, я не видел этого в первом чтении, но я могу понять эту интерпретацию. На самом деле не имело для меня смысла, почему у него были отдельные классы, определенные как «Коллекции» для этого, и поскольку это вопрос с лучшей практикой, я думаю, что управление его типами данных, как я предлагаю, вероятно, является лучшим подходом. Я обновлю, чтобы дать подход к фильтру –

+0

Personaly Я бы сменил коллекцию на многомерный массив, при этом ключ был типом добавленного объекта, как и другой ответ, но динамический. Это увеличило бы производительность imo, потому что вы можете просто вернуть коллекцию на основе типа, а не необходимость выбирать каждый элемент и правильно отображать его – DarkBee

Смежные вопросы