Как правильно организовать классы? Осваиваю возможности php, которых ранее не использовал, попутно переехав с php 5.2 на php 5.6, узнал о PSR-0,1,2,4 наткнувшись на этот (PHP Right Way) документ. Вот ставлю задачу: реализовать возможность работы с различными типами хранилищ(git, mercurial). делаю пакет в котором реализую:Интерфейс: interface RepositoryInterfaceАбстрактный класс: abstract class RepositoryAbstractКласс для работы с хранилищем типа mercurial: class RepositoryHg extends RepositoryAbstract implements RepositoryInterface Далее в коде сайта(или приложения, как будет угодно) я предполагаю, должно быть правильное использование интерфейса RepositoryInterface, на случай если, например, появится класс RepositoryGit, но я ни должен давать сайту(приложению) видеть RepositoryHg или RepositoryGit, если я правильно понял, для чего вообще ООП, ведь суть в том, чтобы ему было всё равно какой класс ему дают, главное чтобы он реализовывал нужный интерфейс. Наверное в RepositoryAbstract должна быть реализован паттерн Фабрика и в приложении должен быть использован только интерфейс, но я не уверен, делаю всё впервые и прошу подсказку. Спасибо.
Да, ваше рассуждение вполне верное. ООП позволяет скрыть реализацию от клиента и работать с объектами по интерфейсу.
Для вашего случая, паттерн Фабрика вполне подходит. В классе RepositoryAbstract вы можете добавить статический метод createRepository(), который будет создавать экземпляр нужного класса в зависимости от переданного типа хранилища.
Примерно так будет выглядеть ваш код:
interface RepositoryInterface { public function commit(); } abstract class RepositoryAbstract { public static function createRepository($type) { switch ($type) { case 'git': return new RepositoryGit(); case 'hg': return new RepositoryHg(); default: throw new Exception("Unsupported repository type"); } } } class RepositoryHg extends RepositoryAbstract implements RepositoryInterface { public function commit() { echo "Committing changes to Mercurial repository"; } } class RepositoryGit extends RepositoryAbstract implements RepositoryInterface { public function commit() { echo "Committing changes to Git repository"; } } // Использование $type = 'git'; // или 'hg' $repository = RepositoryAbstract::createRepository($type); $repository->commit();
Таким образом, у вас будет возможность легко добавлять новые типы хранилищ, не меняя код клиента, так как он будет работать только с интерфейсом RepositoryInterface.
Не забудьте также следовать стандартам PSR-0, PSR-1, PSR-2, PSR-4 для удобства сопровождения и масштабирования вашего проекта.
Да, ваше рассуждение вполне верное. ООП позволяет скрыть реализацию от клиента и работать с объектами по интерфейсу.
Для вашего случая, паттерн Фабрика вполне подходит. В классе RepositoryAbstract вы можете добавить статический метод createRepository(), который будет создавать экземпляр нужного класса в зависимости от переданного типа хранилища.
Примерно так будет выглядеть ваш код:
interface RepositoryInterface {public function commit();
}
abstract class RepositoryAbstract {
public static function createRepository($type) {
switch ($type) {
case 'git':
return new RepositoryGit();
case 'hg':
return new RepositoryHg();
default:
throw new Exception("Unsupported repository type");
}
}
}
class RepositoryHg extends RepositoryAbstract implements RepositoryInterface {
public function commit() {
echo "Committing changes to Mercurial repository";
}
}
class RepositoryGit extends RepositoryAbstract implements RepositoryInterface {
public function commit() {
echo "Committing changes to Git repository";
}
}
// Использование
$type = 'git'; // или 'hg'
$repository = RepositoryAbstract::createRepository($type);
$repository->commit();
Таким образом, у вас будет возможность легко добавлять новые типы хранилищ, не меняя код клиента, так как он будет работать только с интерфейсом RepositoryInterface.
Не забудьте также следовать стандартам PSR-0, PSR-1, PSR-2, PSR-4 для удобства сопровождения и масштабирования вашего проекта.