2014-09-01 3 views
1

Я написал несколько классов, которые необходимо создать при использовании.Статическая ссылка объекта класса

Моя цель состояла в том, чтобы иметь идеальную организацию при попытке создать динамический доступ между экземплярами классов.

В одном классе у него было бы несколько методов, которые он называет, исходя из того, что он только что сделал. Внутри одного из этих методов будут методы из других классов. (В настоящее время статические методы) Я бы отредактировал эти строки, чтобы контролировать поведение между классами.

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

Мой вопрос является предметом озабоченности надлежащего ООП. Я не уверен, есть ли лучший способ, или если что-то может сделать проблемы. Хотя, он работает очень хорошо.

У меня есть пример, подготовленный ниже. Из них - это представление, а не реальная ситуация. executingFileOne - это одна ситуация, а ExecutingFileTwo - другая.

executingFileOne.php

require_once 'login.php'; 
$login = new Login(); 

require_once 'serverData.php'; 
$servDat = new serverData(); 

//blah blah blah 

executingFileTwo.php

require_once 'serverData.php'; 
$servDat = new serverData(); 

//blah blah blah 

login.php

class Login { 

    private static $thisClass = null; 

    public function __construct(){ 
     //Get and set user data. 
     self::setStaticClass($this); 
    } 

    public static function setStaticClass(&$inputClass){ 
     self::$thisClass = $inputClass; 
    } 

    //Methods Methods Methods 

    //---Methods Executed by class at specific times--------------- 
    // - - - Used to get input from other classes 

    //Methods Methods Methods 

    //------------------------------------------------------------- 

    //---Methods for other classes.-------------------------------- 
    // - - - Used to output data to other classes 
    public static function getUserID(){ 
     die('Test'.self::$thisClass->userID); 
    } 

    //Methods Methods Methods of other classes. 

    //------------------------------------------------------------- 
} 

serverData.php

class serverData { 

    private static $thisClass = null; 

    public function __construct(){ 
     //work work work 
     //an IF statement detected needing to register userID on serverData 
      $this->registerOnServer(); 
     //work work work 
     self::setStaticClass($this); 
    } 

    //Methods Methods Methods 

    public function registerOnServer(){ 
     //work work work 
     $this->userID = $this->getUserID(); 
     //add userID to registration data. 
    } 

    //---Methods Executed by class at specific times--------------- 
    // - - - Used to get input from other classes 
    private function getUserID(){ 
     if (class_exists('Login')) { 
      return Login::getUserID(); 
     } else { 
      return 0; 
     } 
    } 
    //------------------------------------------------------------- 

    //---Methods for other classes.-------------------------------- 
    // - - - Used to output data to other classes 

    //Methods Methods Methods of other classes. 

    //------------------------------------------------------------- 
} 
+0

Я не знаком с этой альтернативой. – TrinaryAtom

+0

Я посмотрел, но одна из моих проблем заключается в том, что в определенных ситуациях один класс не вызывается все время. Чтобы это сработало, мне пришлось бы редактировать сотни страниц, чтобы это работало. И если бы я изменил его, мне потребовалось бы отредактировать эти сотни файлов ... Я думаю. Возьмем, к примеру, класс Login требуется классу serverData, но класс Login не всегда доступен. – TrinaryAtom

+0

Ahh, исправление старого кода может быть .. проблемой. Вот почему я начинаю все новые проекты с DI/IoC с самого начала. Во всяком случае, хороший контейнер IoC также будет поддерживать * дополнительные зависимости * или, альтернативно, можно использовать * mock зависимость * (он выполняет требование DI, но на самом деле «ничего не делает», если он используется). Важно то, что что один и тот же интерфейс предоставляется (и что служба работает как ожидалось в контексте). – user2864740

ответ

2

Это один из нескольких вопросов, при использовании статических классов, и это усугубляется из-за трусливую самостоятельную регистрацию и сильной связь в использовании-сайте. В настоящее время «лучшее» решение, которое я знаю об этой проблеме в целом, и тот, к которому я призываю, к этой проблеме - использовать Injection Dependency.

Кроме того, с помощью контейнера IoC (инверсия управления) поверх DI можно сделать все вместе и управлять жизненным циклом разумного процесса. (! У не вернуться к шаблону Service Locator, за исключением особых случаев или beautiy ДИ + IoC теряются)

Хотя неофициальная утка типизированного «интерфейс» достаточно, с помощью кодифицированных интерфейсов помогает при классификации - и часто (но не всегда), необходимые для контейнеров IoC, чтобы иметь возможность регистрировать и разрешать компоненты.

// This is the service (interface) that different components will provider 
inteface ILogin { 
    public function getUserID(); 
} 

// Primary component (implementation) for the login service (interface) 
class Login implements ILogin { 
    // Note: 
    // Constructor does NOT "register itself statically"; even when using 
    // an approach similar to the original, use a proper Singleton Design. 

    public function getUserID() { /* .. */ } 
} 

// Alternative/mock component (implementation) for the login service (interface) 
class NoLogin implements ILogin { 
    public function getUserID() { return 0; } 
} 

// Class (possibly also a component) that uses the login service dependency 
class ServerData { 
    // Constructor-based DI; the components are supplied as arguments 
    // (There is also property-based DI.) 
    public function __constructor(ILogin $login) { 
     $this->login = $login; 
    } 

    // Later on we use the service 
    // (It is a bit silly just to proxy the service, which should be 
    // injected elsewhere as required, but this mirrors the original.) 
    public function getUserID() { 
     // If not using a "mock service", then guard $this->login for null 
     // because it is now an optional dependency; the appropriate approach 
     // will vary based upon specific use-case. 
     return $this->login->getUserID(); 
    } 
} 

Тогда позже:

// File 1- 
// Note how dependency is "injected" into the server data 
$servDat = new ServerData(new Login()); 

// File 2- 
// A different dependency providing the same contract/service is used 
$servDat = new ServerData(new NoLogin()); 
// Or, if ServerData guards usage and the service is "optional" 
// $servDat = new ServerData(null); 

Так что это одна из форм DI (хотя общий термин IoC, из которых DI является реализация) в ядре - простой, но не очень интересно и он может стать утомительным. Кроме того, несмотря на то, что зависимости были перемещены «снаружи» на сайт немедленного использования, они по-прежнему эффективно представляют собой жесткий код у потребителя, создающего экземпляр, и ручную инъекцию компонентов.

Теперь, где магия с DI + IoC вписывается? Компоненты регистрируются в контейнере IoC, а контейнер IoC используется для создания объектов - такой контейнер достаточно умен, чтобы автоматически разрешал зависимостей DI. Тогда единственное различие между File # 1 и File # 2 заключается в том, что они используют немного другую конфигурацию IoC (один использует Login и другой NoLogin для службы ILogin).

Другая полезная функция IoC - это способность настраивать время жизни объекта. В этом случае компонент Login (выполняющий службу входа) может быть экземпляром для запроса, который фактически является «однопользовательским поведением», за исключением того, что он не может протекать между запросами и. Элемент Login теперь слабо связан с ServerData класс.

Существует много больше к контейнеру IoC - см. PHP DI, который, кажется, имеет довольно хорошее представление. Обратите внимание, что такой же код DI-ready, который был представлен выше, может использоваться (в PHP-DI) для разрешения компонента. (Ошибки бесплатны.)

+0

У вас репутация 21K, и вы даже не удосужились ввести ник? – Yang

+0

@bad_boy Может быть, я набрал «user2864740»: D (Но на самом деле я полюбил этот номер - как первый номерной знак.) – user2864740

+0

Ну, это не очень приятно, так или иначе ... Если вы только набрали прозвище, тогда вы выглядели бы лучше. Это связано с тем, что мы все видим дерьмовые вопросы и ответы пользователей со случайными числами с 1 или около – Yang

0

Мой друг показал мне вариант, который лучше подходит, чем мой. Наверное, это не правильное решение, но лучше.

Видя, как я создаю экземпляры своих классов и могу просто получить доступ к другим классам, вызвав переменную глобально. Вместо того, чтобы создавать что-либо статичное.

Например:

require_once 'login.php'; 
$login = new Login(); 

require_once 'serverData.php'; 
$servDat = new serverData(); 

//blah blah blah 


class Login { 

    public function __construct(){ 
     //Get and set user data. 
    } 

    //Methods Methods Methods 

    //---Methods Executed by class at specific times--------------- 
    // - - - Used to get input from other classes 

    //Methods Methods Methods 

    //------------------------------------------------------------- 

    //---Methods for other classes.-------------------------------- 
    // - - - Used to output data to other classes 
    public static function getUserID(){ 
     die('Test'.$this->userID); 
    } 
    //------------------------------------------------------------- 
} 

class serverData { 

    public function __construct(){ 
     //work work work 
     //an IF statement detected needing to register userID on serverData 
      $this->registerOnServer(); 
     //work work work 
    } 

    //Methods Methods Methods 

    public function registerOnServer(){ 
     //work work work 
     $this->userID = $this->getUserID(); 
     //add userID to registration data. 
    } 

    //---Methods Executed by class at specific times--------------- 
    // - - - Used to get input from other classes 
    private function getUserID(){ 
     global $login; 
     if ($login != null) { 
      return $login->getUserID(); 
     } else { 
      return 0; 
     } 
    } 
    //------------------------------------------------------------- 

    //---Methods for other classes.-------------------------------- 
    // - - - Used to output data to other classes 

    //Methods Methods Methods 

    //------------------------------------------------------------- 
} 
Смежные вопросы