Я использую шаблон проектирования Decorator в PHP, и у меня есть проблема со структурой.
Вот простой пример, иллюстрирующий мою проблему:
interface MyInterface {
function showUsers($array);
function showUser($i);
}
class MyCLass implements MyInterface {
function showUsers($array)
{
foreach($array as $toto) {
$this->showUser($toto);
}
}
function showUser($i)
{
echo $i;
}
}
class MyCLassDecorator implements MyInterface {
private $inner;
public function __construct(MyInterface $inner)
{
$this->inner = $inner;
}
function showUsers($array)
{
$this->inner->showUsers($array);
}
function showUser($i)
{
echo "User: $i";
}
}
class MyCLassDecorator2 implements MyInterface {
private $inner;
public function __construct(MyInterface $inner)
{
$this->inner = $inner;
}
function showUsers($array)
{
$this->inner->showUsers($array);
}
function showUser($i)
{
$this->inner->showUser($i);
echo " is wonderful";
}
}
$myClass = new MyCLassDecorator2(new MyCLassDecorator(new MyCLass()));
$myClass->showUsers(["Alfred", "Bob", "Claire"]);
С этим кодом методы showUser из MyClassDecorator & MyClassDecorator2 никогда не будет вызываться.
Что я могу сделать?
Запрещено ли вызывать другой метод того же класса? (Не очень удобно разбивать мой код)
Есть ли другой способ сделать это?
Должен ли я создать один интерфейс по методу?
Большое спасибо 🙂
РЕДАКТИРОВАТЬ:
Вот решение, которое я наконец-то использовал, хотя я не очень доволен им …
Я делю код не по методам, а по интерфейсам (сервисам)
Вот :
interface IShowUsers {
function showUsers($array);
}
interface IShowUser {
function showUser($user);
}
class Services {
static $showUsers;
static $showUser;
}
class MyShowUsers implements IShowUsers {
function showUsers($array)
{
foreach($array as $toto) {
Services::$showUser->showUser($toto);
}
}
}
class MyShowUser implements IShowUser {
function showUser($user)
{
echo $user;
}
}
class MyShowUserDecorator implements IShowUser {
private $inner;
public function __construct(IShowUser $inner)
{
$this->inner = $inner;
}
function showUser($user)
{
echo "User: ";
$this->inner->showUser($user)
}
}
class MyShowUserDecorator2 implements IShowUser {
private $inner;
public function __construct(MyInterface $inner)
{
$this->inner = $inner;
}
function showUser($user)
{
$this->inner->showUser($user);
echo " is wonderful";
}
}
$myClass = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser()));
Services::$showUsers = new MyShosUsers();
Services::$showUser = new MyShowUserDecorator2(new MyShowUserDecorator(new MyShowUser()));
Services::$showUsers->showUsers(["Alfred", "Bob", "Claire"]);
Если у вас есть лучшее решение, я буду рад узнать это 🙂
Конечно, я использую шаблон декоратора, чтобы использовать эти декораторы по-разному во многих проектах, как в следующих примерах:
//no decorators
Services::$showUser = new MyShowUser();
//only the first
Services::$showUser = new MyShowUserDecorator(new MyShowUser());
//only the second
Services::$showUser = new MyShowUserDecorator2(new MyShowUser());
Таким образом, расширение не кажется хорошим решением.
Еще раз большое спасибо за то, что дали правильный способ сделать это 🙂
Мне кажется, вам нужно немного подумать об этом. Если вы можете дать четкое представление о том, чего вы пытаетесь достичь, тогда мы сможем предоставить вам более глубокое понимание. Но ответить на ваш вопрос напрямую вы можете extend
класс, а затем override
метод.
http://sandbox.onlinephpfunctions.com/code/61c33b0ce98631986134bf78efcd0391f9b9ab67
<?php
interface MyInterface {
function showUsers($array);
function showUser($i);
}
class MyCLass implements MyInterface {
function showUsers($array = ["Alfred", "Bob", "Claire"])
{
foreach($array as $toto) {
$this->showUser($toto);
}
}
function showUser($i)
{
echo $i;
}
}
// Extend the class in order to override the methods.
class MyCLassDecorator extends MyCLass {
// Also, try removing this method to see what it does.
function showUsers($array = [1,2,3])
{
foreach($array as $toto) {
$this->showUser($toto);
}
}
function showUser($i)
{
echo "c'est la fete chez $i";
}
}
$myClass = new MyCLassDecorator();
$myClass->showUsers();
РЕДАКТИРОВАТЬ
Не уверен, ясно ли мне, но проблема в том, что вы ожидаете наследственное поведение без использования наследование. Как MyCLass
должен знать о MyCLassDecorator::showUser
?
foreach($array as $toto) {
// The issue is this line. You're mixing `decorator` and `inheritance`.
// You should re-think your design. This will not work.
$this->showUser($toto);
}
Других решений пока нет …