У меня есть некоторая путаница с шаблоном адаптера, и мне интересно, является ли это правильный инструмент для того, что я пытаюсь достичь.
По сути, я пытаюсь добиться того, чтобы класс, написанный другим разработчиком, соответствовал написанному мною интерфейсу, сохраняя при этом другие методы этого класса.
Итак, я написал следующий интерфейс для объекта контейнера:
interface MyContainerInterface
{
public function has($key);
public function get($key);
public function add($key, $value);
public function remove($key);
}
Я также написал адаптер, который реализует этот интерфейс:
class OtherContainerAdapter implements MyContainerInterface
{
protected $container;
public function __construct(ContainerInteface $container) {
$this->container = $container;
}
public function has($key) {
$this->container->isRegistered($key);
}
...
}
И я использую это в моем классе следующим образом:
class MyClass implements \ArrayAccess
{
protected $container;
public function __construct(MyContainerInterface $container) {
$this->setContainer($container);
}
public function offsetExists($key) {
$this->container->has($key);
}
...
}
Тогда мое приложение использует класс так:
$myClass = new MyClass(new OtherContainerAdapter(new OtherContainer));
У меня проблема в том, что для того, чтобы использовать методы из адаптера, я должен написать следующее:
$myClass->getContainer()->getContainer()->has('some_key');
Когда в идеале это будет просто:
$myClass->getContainer()->has('some_key');
$myClass->getContainer()
должен вернуть экземпляр MyContainerInterface
и это имеет has()
функция. Это не должно иметь getContainer()
функция.
Я не думаю, что вам нужен шаблон адаптера для этого. Мне кажется, что вы ищете полиморфное решение, которое может быть достигнуто простым использованием абстрактного класса. Адаптер не нужен.
Интерфейс
interface MyContainerInterface
{
public function has($key);
public function get($key);
public function add($key, $value);
public function remove($key);
}
Тогда абстрактный базовый класс:
class MyContainerBaseClass implements MyContainerInterface, \ArrayAccess
{
public function offsetExists($key) {
$this->has($key);
}
...
}
Затем подкласс от другого разработчика:
class ClassByOtherDeveloper extends MyContainerBaseClass
{
public function has($key) {
$this->isRegistered($key);
}
//you also need to implement get(), add(), and remove() since they are still abstract.
...
}
Вы можете использовать его в своем приложении следующим образом:
$object = new ClassByOtherDeveloper();
$x = $object->has('some_key');
Я предполагаю isRegistered
Метод живет в реализации от другого разработчика.
Чтобы сделать его по-настоящему полиморфным, вам не нужно было бы жестко кодировать имя класса, но вы бы использовали переменную, которая может быть получена из файла конфигурации, базы данных или фабрики.
Например:
$className = "ClassByOtherDeveloper"; //this could be read from a database or some other dynamic source
$object = new $className();
$x = $object->has('some_key');