Определения:
Статическим классом (далее СК) называют класс, содержащий только статические методы и свойства. У него нет конструктора и деструктора, создание экземпляра СК в PHP физически возможно но не имеет смысла.
Мало ебучий фактор (далее МЕФ) — обстоятельство, не имеющее большого значения в рассматриваемом контексте.
Плюсы:
1. Быстродействие. Скорость обращения к статическим свойствам и методам близка к скорости обращения к локальным переменным и простым функциям, то есть в несколько раз быстрее, чем обращение через экземпляр класса. (поправка 2009-09-12: это надо проверить! тыц)
2. Упрощение и сокращение кода. Нет необходимости создавать экземпляр класса, следить за тем что переменная-объект класса инициирована в нужный момент или что конструктор не вызывается лишний раз. Во многих приложениях бОльшая часть объектов существует в единственном числе, т.е. может (хотя не обязана) реализоваться как Singleton. СК обеспечивает такой функционал "от природы". Подключение классов можно реализовать через автолоадер: не понадобится явно описывать require('path.to.class.unit.php'). Просто упоминаем имя класса, там где надо.
3. Пространство имен. Конструкции namespace отсутствует в PHP < 5.3, а он еще не начал своё победное шествие. Программист может объявить СК даже в том случае, когда его устроил бы простой набор функций, только чтобы не засорять общее пространство имен. Создавать экземпляр такого класса не требуется!
Простой пример — "конфигурация приложения" — набор параметров, используемых в различных частях программы.
Минусы:
1. Нет конструктора — нет точки в которой мы могли бы выполнить начальную инициализацию свойств класса.
2. Есть сложности в реализации полиморфизма, т.к. нет экземпляров классов. Вызов метода содержит явное обращение к конкретному классу.
3. Возможен конфликт с привычными методологиями. Например юнит-тесты требуют уменьшения связанности кода. Модный прием — Внедрение зависимости т.е. передача готовых объектов на вход конструктору тестируемого класса. Вспомогательные объекты должны создаваться где-то там далеко, поэтому в самом тестируемом модуле классы объектов явно не упоминаются.
А в наших СК нет ни "конструктора", ни "готовых объектов". Класс всегда упоминается явно.
Workaround:
Я считаю, что указанные минусы это МЕФ.
1. Код инициализации можно поместить в модуль класса ниже описания самого класса. Этот код выполнится строго один раз перед первым использованием класса. (поправка: код будет выполнен при подключении модуля, если используется автолоадер — то да, получится перед первым использованием класса)
А если требуется "ленивая инициализация" — то она делается так же как в не-статических классах, как-то так:
if (!self::$_initiated) self::_init();
2. Если рефакторинг под использование СК не получается, а хочется полиморфизма, выкрутимся с помощью
call_user_func(array('class', 'method'));
Лишь бы такие заглушки были исключением, а не правилом.
3. Внедрение зависимостей можно обеспечить, если мы пойдём на такую уловку: классы подгружаем через автолоадер, а пути к загружаемым файлам описываем в файле конфигурации.
array(
'ClassA' => 'path.to.my.mocup.class_a.php',
'ClassB' => 'path.to.my.mocup.class_b.php',
…
)
Таким образом, хотя классы упоминаются явно, мы можем заменять окружение тестируемого модуля за счет настраиваемой конфигурации.
Выводы:
Мы можем повысить скорость приложения и в некоторых случаях упростить наш код за счет использования СК. Насколько эффективной будет эта методика зависит от контекста и наших способностей.
(дополнение от 2009-09-12: хаки __get/__set — в СК невозможны)