Глобальный против функции против статического метода класса - PullRequest
5 голосов
/ 09 февраля 2012

Допустим, у вас есть уникальный объект, который используется всеми другими классами и функциями ... что-то вроде $application.

Как бы вы получили доступ к этому объекту в своих функциях?

  1. с использованием глобальной переменной в каждой из ваших функций:

    global $application;
    $application->doStuff();
    
  2. создание функции, подобной application(), которая создает экземпляр объекта в статическую переменную и возвращает его; затем используйте эту функцию везде, где вам нужно получить доступ к объекту:

    application()->doStuff();
    
  3. создайте одноэлементную вещь, как статический метод внутри класса объекта, который возвращает единственный экземпляр, и используйте этот метод для доступа к объекту:

    Application::getInstance()->doStuff();
    
  4. KingCrunch & skwee: передать объект приложения в качестве аргумента каждой функции / классу, где это необходимо

    ...
    public function __construct(Application $app, ...){
      ....
    

Если есть другие варианты, пожалуйста, оставьте их. Мне интересно, какой из этих вариантов является наиболее эффективным / считается "наилучшей практикой".

Ответы [ 3 ]

4 голосов
/ 09 февраля 2012

Синглтоны, Бог-классы, монолитные классы и т. Д. Являются анти-паттернами, поэтому я бы предложил четвертый вариант: внедрение зависимостей. Вы можете создать экземпляр application в своем приложении через фабрику (или, возможно, даже new, если у него нет зависимостей, но это может усложнить ситуацию позже).

Тогда любой класс, которому нужен доступ к application, может получить его в качестве члена, с помощью конструктора. Я уверен, что не каждому классу нужен доступ к application. Помни Закон Деметры.

Если вам нужны некоторые общие функции, такие как преобразование одной статической строки в другую, я предлагаю использовать глобальные функции php (в отличие, например, от искусственного статического класса). Я считаю, что они были разработаны для этой цели.

4 голосов
/ 09 февраля 2012

Я бы передал это всем необходимым методам.то есть

function doFoo(Application $app) {
    $app->doStuff();
}

И глобальный, и синглтон считаются плохими и слишком сильно связывают ваш код, что затрудняет модульное тестирование.Существует одно правило, когда вам разрешено использовать синглтон, если вы отвечаете «да» на следующее утверждение:

Нужно ли вводить глобальное состояние в мое приложение И у меня должен быть один экземплярданный объект И наличие более одного экземпляра вызовет ошибку

Если вы ответите «да» на все 3 части, вы можете использовать синглтон.В любом другом случае просто передайте все экземпляры всем методам, которым они нужны.Если у вас их слишком много, подумайте о том, чтобы использовать что-то вроде Context

class Context {
    public $application;
    public $logger;
    ....
}
========
$context = new Context();
$context->application = new Application();
$context->logger = new Logger(...);
doFoo($context);
========
function doFoo(Context $context) {
    $context->application->doStuff();
    $context->logger->logThings();
}

(вы можете использовать методы получения / установки, если вам нужно защитить данные или манипулировать ими, или если вы хотите использовать ленивую инициацию и т. Д.).

Удачи!

1 голос
/ 09 февраля 2012

Или просто отдайте его тем, кто в этом заинтересован. Все ваши предложения похожи на глобальные переменные, даже если вы называете это не так в 2 из 3 вариантов.

Прежде чем до этого дойдет: Если вы хотите сказать: «Это невозможно, потому что все нуждается в этом», чем, может быть, слишком много, слишком много и / или слишком много знает.

...