2013-02-23 4 views
1

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

Одно из предложений, сделанное моим другом, состояло в том, чтобы использовать конструктор с параметрами, которые могут быть настроены во время строительства. Для целей этой библиотеки это невозможно. Рассматриваемые классы предназначены для расширения, и я не хотел навязывать какие-либо странные требования к параметрам конструктора, если пользователи хотят иметь свои собственные конструкторы. Еще сложнее то, что некоторая информация, используемая для конфигурации, недоступна для пользователя. Я должен был бы сделать его доступным для пользователя и верю, что он вернет его в соответствующие классы во время строительства.

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

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

Редактировать: Я должен объяснить цель этой архитектуры. Каждый класс выполняет определенную задачу в стеке операций. Задача центрального класса состоит в том, чтобы командовать одним классом выполнять свою задачу, собирать результаты и распределять результаты другим классам, которые в них нуждаются. Затем класс переходит к следующему классу и делает то же самое. Как выполняются задачи, зависит от расширенного класса. Методы, которые я хочу ограничить, - это те, которые помогают в диспергировании результатов. Надеюсь, что мои намерения станут более ясными.

+1

Запрет уродливых хаков, вы не можете ограничить, кто вызывает ваши методы. Похоже, что ваши занятия не очень хорошо разработаны. Каждый должен стоять сам по себе и не быть зависимым от того, чтобы его называли каким-либо особым образом. – deceze

+4

Вы не можете блокировать доступ к общедоступным методам, поэтому они называются общедоступными. И если у вас есть один класс, который использует большинство других классов в системе, то вы, вероятно, строите антипаттерн Бога-объекта. http://en.wikipedia.org/wiki/God_object. Лучше, чтобы каждый класс был автономным и отвечал за собственную конфигурацию. – GordonM

+0

Почему бы не «расширить» родителя и не использовать защищенные методы? –

ответ

0

Все зависит от роли вашего центрального класса. Из вашего описания это похоже на спулер или планировщик. Если буферизованные объекты фактически созданы этим центральным классом, вы можете скрыть объекты от клиента, сделав эти объекты частными, а затем создайте заглушки в центральном объекте, что позволяет клиенту вызывать функции, которые вы разрешаете.

E.g. (Концептуальный код, не может компилировать)

class HiddenSubClass { 
    public function MyFunc() { 
    echo "hello"; 
    } 
} 

class CentralClass { 
    private $obj; 

    function __construct() { 
    $obj=new HiddenSubClass(); 
    } 

    function SubClassMyFunc() { 
    $obj->MyFunc(); 
    } 
} 

Клиент имеет только объект CentralClass и, следовательно, может вызвать только SubClassMyFunc, но не MyFunc. Недостатком этого является то, что это также скроет объектно-ориентированную структуру библиотеки от клиента, что может быть или не быть желательным.

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

Edit: Если вы хотите, чтобы «взломать» это, это будет один подход (хотя я не рекомендую, потому что это довольно вонючий):

Есть «частный секрет» в вашей центральный класс.

class CentralClass { 
    private $MySecret=42; 

    function IsValidSecret($anumber) { 
    return ($anumber==$this->MySecret); 
    } 
} 

Теперь центральный класс может передать $ MySecret в качестве параметра, при вызове определенной «защищенной» функции на буферных объектах. Если CentralClass является одиночным, буферный объект может вызывать этот синглтон, чтобы проверить, правильно ли переданный секрет. Если CentralClass не является одиночным, вам также придется передать этот объект.

class MySpooledObject { 
    function SuperSecretFunction ($asecret) { 
    if (!$CentralSingleton->isValidSecret($asecret)) { die(); } 
    } 

    function SuperSecretFunction2 ($acentralobject,$asecret) { 
    if (!$acentralobject->isValidSecret($asecret)) { die(); } 
    } 
} 

Существует много вариантов этого. Центральный класс мог установить внутренний флаг перед вызовом метода объекта и сбросить его после его возврата. В этом случае объект может запросить центральный класс, если этот флаг установлен, и секрет не должен передаваться. Вам все равно понадобится $ acentralobject, если только он не является синглом.

+1

Второй случай, о котором вы упоминали (они его создают), - это то, как это работает. Вы правы в центральном классе; называя его спулер будет довольно точным (это первый раз, когда я сталкивался с этим термином, спасибо за новый vocab). Похоже, если я действительно хочу, чтобы пользователи не вызывали его, мне пришлось бы взломать его. Думаю, мне придется либо разобраться, либо изменить архитектуру. – dawsonc623

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