2015-02-13 2 views
0

В моем классе мы создали простое приложение с использованием MVC с шаблоном наблюдателя в Java и оно работает. Представление не может вызывать любые методы из модели, которые не входят в интерфейс (Observable) и наоборот.OO, MVC и шаблон наблюдателя работают не так, как ожидалось

Я довольно поклонник PHP и решил сделать тот же (упрощенный) пример в PHP. Я заметил, что, хотя я использую интерфейс и передаю ссылку модели в качестве интерфейса, вид все равно может вызвать каждый метод внутри модели, делая весь рисунок бесполезным.

Есть ли что-то, что я забыл или это невозможно в PHP?

РНР код (каждая ссылка, метод и т.д. точно такой же, как и в приложении Java):

class App 
{ 
    public function __construct() 
    { 
     $model = new Model(); 
     $controller = new Controller($model); 
    } 

} 

class Model implements Observable 
{ 
    private $view; 
    private $count = 1; 

    public function __construct() 
    { 
     echo 'Model created. <br>'; 
    } 

    public function registrate(Observer $view) 
    { 
     $this->view = $view; 
     echo 'Model: view is registered. <br>'; 
    } 

    public function addOne() 
    { 
     $this->count += 1; 
     $this->view->modelChanged($this); 
    } 

    public function getCounter() 
    { 
     return $this->count; 
    } 

    public function getMessage() 
    { 
     return 'The view should not be able to call this method.'; 
    } 

} 

class Controller 
{ 
    private $view; 
    private $model; 

    public function __construct(Model $model) 
    { 
     echo 'Controller created. <br>'; 
     $this->model = $model; 
     $this->view = new View($this->model); 
     $this->model->addOne(); 
    } 

} 

class View implements Observer 
{ 
    public function __construct(Observable $model) 
    { 
     echo 'View created. <br>'; 
     $model->registrate($this); 
    } 

    public function modelChanged(Observable $model) 
    { 
     // Should only be able to call method "getCounter()" 
     echo $model->getMessage(); 
    } 

} 

interface Observable 
{ 
    public function registrate(Observer $view); 
    public function getCounter(); 
} 

interface Observer 
{ 
    public function modelChanged(Observable $model); 
} 

Выход, если вы запустите это: создается

модели.

Контроллер создан.

Открыть создано.

Модель: вид зарегистрирован.

Вид не должен называть этот метод. Как вы можете видеть, представление может вызывать метод модели, который не, объявленный внутри интерфейса Observable.

Как это возможно и почему это не работает на PHP, как в Java?

+0

Этот вопрос кажется более подходящим для [codereview] (http://codereview.stackexchange.com/), разместите его там, вы, скорее всего, получите исчерпывающий ответ, объясняющий возможные недостатки в вашем дизайне, некоторые советы и ссылки на полезные ресурсы –

+0

@EliasVanOotegem кажется, что что-то не так с кодом 'view не должно быть в состоянии вызвать этот метод'. В последнем предложении спрашивается, почему он не работает так, как предполагалось. это вне темы на CR – Malachi

+0

@Malachi: Это не столько проблема с кодом, сколько в случае путаницы. OP ожидает, что интерфейсные подсказки заставят PHP вести себя так же, как Java.Простой факт заключается в том, что PHP не является Java, что бы тщательно проанализировал код, наряду с предоставлением альтернативных предложений и поддержкой тех, с документацией. Это пограничная линия вне темы на CR, так же, как она есть здесь: это не проблема, связанная с кодом, более «понимание того, как язык X отличается от языка Y» _ question –

ответ

1

Ну, конечно же, вид может позвонить каждый метод вы определили на модели: Все методы общественного, что означает, что они отозваны из любой точки мира. Просто определите их как protected или private ...

Конечно, это ограничило бы способы использования модели в других компонентах (таких как контроллер). Чтобы обойти эту проблему, простое исправление было бы создать оболочку, которую можно обернуть вокруг модели, когда вы передаете его к виду:

class View implements Observable 
{ 
    public function __construct(ViewObservable $model) 
    { 
     //do stuff here 
    } 
} 
//Wrapper: 
class ViewObservable 
{ 
    /** 
    * @var Model 
    */ 
    protected $payload = null; 
    public class __construct(Observable $model) 
    { 
     $this->payload = $model; 
    } 
    public function getCounter() 
    { 
     return $this->payload->getCounter(); 
    } 
} 

Но на самом деле, вы можете захотеть пересмотреть вещь или 2 . Хорошо использовать интерфейсы, но не имеет большого значения (по крайней мере для меня) иметь все компоненты в архитектуре MVC реализуют один и тот же интерфейс. Все компоненты выполняют разные задания и поэтому должны иметь разные требования к интерфейсу.

+0

. Тогда как контроллер может их называть? – aaa

+0

@aaa: Ответ на этот вопрос, обновив мой ответ: у вашего представления нет одинаковых прав доступа/разрешений в качестве контроллера (поскольку его обязанности различны), следовательно, контракт, который выполняет ваш класс 'View', должен быть другим: вы должны «Разрешено пропускать интерфейсы« Наблюдаемые »к представлению точно так же, требования должны быть более строгими. Проблема, к которой я обратился, просто усиливая подсказки типа и предоставляя класс-оболочку –

+0

Я понимаю, что вы имеете в виду, и я вижу, что это действительно сработает. Однако в чем смысл «моих» текущих интерфейсов, если они не могут скрыть какие-либо данные/методы. Теперь они работают точно так же, как абстрактный класс, помимо того факта, что они могут стать объектом. Пример, приведенный выше, гарантирует, что представление может получить доступ только к способам, объявленным в интерфейсе (Observable), как это работает в Java по крайней мере. Итак, вы сказали бы, что «единственный» способ сделать то же самое в PHP - это пример, который вы указали выше? – aaa

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