Я ищу архитектурное решение для создания экземпляров различных дочерних классов на основе типа объекта или расширения базового класса с помощью методов дочерних классов.
Чтобы привести пример: существует базовый класс User и несколько дочерних классов Partner , Client , Moderator, которые имеют конкретные методы и свои собственные конструкторы. Когда я звоню
$user = new User($userid);
Я хочу класс пользователя
class User { public function __construct($userid) { self::initDB(); if ($this->isPartner()) { //extend this class with the methods of "Partner" child class and run "Partner" class constructor } if ($this->isClient()) { //extend this class with the methods of "Client" child class and run "Client" class constructor } if ($this->isModerator()) { //extend this class with the methods of "Moderator" child class and run "Moderator" class constructor } } }
Чтобы вернуть мне объект со всеми методами в зависимости от того, какие роли у пользователя есть.
Я знаю, что моя логика сломана где-то, и пример, который я представил, ошибочен. Но единственным решением, которое я вижу сейчас, является создание одного гигантского класса, который имеет все методы для всех ролей, которые выглядят как беспорядок.
Прежде всего, ваша логика базы данных должна быть полностью отделена от ваших объектов домена (Пользователь и т. Д.). В противном случае вы нарушаете принцип единой ответственности (СРП).
Настройте свои классы примерно следующим образом (базовый класс User и несколько подклассов):
class User { private $id; // getters and setters go here } class Moderator extends User {} class Partner extends User {} // etc
Затем создайте класс UserManager
который реализует интерфейс, который выглядит следующим образом:
interface UserManagerInterface { function loadUserById($id); }
Реализация этого метода должна загружать переданную информацию идентификатора пользователя из базы данных, посмотреть, какой тип она (партнер, модератор и т. Д.), А затем создать экземпляр соответствующего класса и увлажнить соответствующую информацию.
Проблема заключается в том, что вы не можете вызвать new User
и получить что-либо другое, кроме объекта User
.
Это звучит как идеальный вариант использования для заводской картины.
Простейшая форма этого метода использует статический метод для вызова правильного конструктора.
Таким образом, у вас может быть такой код:
class User { public static function create($userid) { // get user from the database // set $isPartner to true or false // set $isClient to true or false // set $isModerator to true or false if ($isPartner) { return new Partner($userid); } elseif ($isClient) { return new Client($userid); } elseif ($isModerator) { return new Moderator($userid); } else { return new User($userid); } } }
Затем вы можете вызвать User::create($userid)
чтобы получить соответствующий объект.
Если ваш код надлежащим образом структурирован, вполне возможно иметь код в соответствии с ответом Лузитанана (fleshed out), который будет делать более гибкую работу.