2013-05-25 2 views
-2

Я получаю объект во время некоторого процесса, и этот объект должен выяснить его схему раскраски. Например, у меня есть схемы окраски, которая хранится так:Ссылка на класс программно в PHP

class FirstScheme { 
    public static $COLORS = array('1' => 'green', '2' => 'red', ...); 
} 
class SecondScheme { 
    public static $COLORS = array('1' => 'red', '2' => 'green', ...); 
} 

Я знаю, что все имена схем раскраски заранее; они могут меняться только при изменении кода. Но схему раскраски, которая будет использоваться для каждого объекта, должна определяться во время выполнения путем сопоставления атрибута этого объекта.

И здесь я не знаю, что делать. В питона я определил бы ДИКТ проведение сопоставления цветовых схем с именами, как это:

d = {'attr_value1': FirstScheme, 'attr_value2': SecondScheme, 'attr_value3': FirstScheme, ...} 

А затем просто получить доступ к переменной «Colors», потому что каждый класс должен иметь. Но в PHP нет способа ссылки на класс таким образом, так что это правильный способ сделать это? Обратите внимание, что более одного атрибута можно сопоставить с той же схемой раскраски.

+2

Что делать, если вы передаете объекты, а не классы? Статические методы/свойства обычно считаются плохой практикой. В случае объектов - у вас будет один класс «ColorScheme» и создайте его с помощью разных схем. – zerkms

+0

Почему? Я не понимаю, зачем мне нужен объект, когда мои схемы окраски заранее определены. Мне не нужно создавать их, я знаю их заранее. – dragoon

+0

как факт, что они предопределены, изменяет тот факт, что решение со статикой отстойно? Создайте построитель, который создает различные цветовые схемы по запросу и связывает ваши классы по интерфейсам, а не по жестко закодированным именам классов и свойств. – zerkms

ответ

2

Если каждый класс должен иметь цвета, определить интерфейс, который позволяет получить их:

interface ColorsProvider { 
    function getColors(); 
} 
class FirstScheme implements ColorsProvider { 
    public static COLORS = array('1' => 'green', '2' => 'red', ...); 

    public function getColors() { 
     return self::COLORS; 
    } 
} 
class SecondScheme implements ColorsProvider { 
    public static COLORS = array('1' => 'red', '2' => 'green', ...); 

    public function getColors() { 
     return self::COLORS; 
    } 
} 

Тогда, где вы стопка YOUT Params:

$a = array(
    'attr_value1' => new FirstScheme(), 
    'attr_value2' => new SecondScheme(), 
); 

Вы можете позвонить:

$param = 'attr_value1'; 

if(!isset($a[$param])) 
    throw new Exception("undefined param"); 

if(!($a[$param] instanceof ColorsProvider)) 
    throw new Exception("Param should point to ColorsProvider"); 

$a[$param]->getColors(); 

Обратите внимание: это полностью объектив. В PHP есть более простые способы получить эти эффекты, но мое решение просто элегантно.


Другая точка является интерфейсом полностью отделяет источник цветов. Там будет из файла, базы данных, XML, закодированного и т.д.


Реализация по умолчанию может быть:

abstract class DefaultColorsProviderImpl implements ColorsProvider    { 
    protected static COLORS = array(); 

    public function getColors() { 
     return self::COLORS; 
    } 
} 

class FirstScheme extends DefaultColorsProviderImpl { 
    protected static COLORS = array(...); 
} 

Но все же позволяет сделать общую реализацию, которая возвращает цвет из e.x. из файла.

+0

'getColors()' реализация может (должна?) Быть перемещена в родительский абстрактный класс. И свойство цвета не обязательно должно быть публичным или статическим – zerkms

+0

, но это решение (с использованием интерфейсов) позволяет получать цвета из любого источника, только из жестко заданного массива (как я уже упоминал). Другим способом является реализация по умолчанию ('ColorsProviderArrayImpl'), которая возвращает цвета из массива (и это популярное решение, что вы упомянули, но все же основано на интерфейсах, которые позволяют создавать совершенно другую реализацию). – Athlan

+0

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

1

Альтернативой жесткого кодирования цвета в своих собственных классов будет следующий подход:

class ColorScheme { 

    protected $colors; 

    public function __construct(array $colors) { 
     $this->colors = $colors; 
    } 

    public function getColors() { 
     return $this->colors; 
    } 

} 

$scheme1 = new ColorScheme(array('red', 'blue', 'green')); 
$scheme2 = new ColorScheme(array('yellow', 'pink', 'cyan')); 

Эквивалент для словаря питона в PHP является ассоциативным массивом. Таким образом, вы можете сделать это:

$d = array (
    'values_1' => $scheme1->getColors(), 
    'values_2' => $scheme2->getColors() 
); 
+0

Я до сих пор не понимаю, как мне получить сопоставления во время выполнения. – dragoon

+0

'$ mapping = $ schem1-> getColors();' Или что вы имеете в виду под «mapping»? – hek2mgl

+0

Хорошо, я попытаюсь объяснить по-другому. У меня есть схемы окраски, как некоторые из них. Они известны заранее. И они во время выполнения у меня есть входящие объекты, которые обладают атрибутом, который позволяет узнать схему, которую мне нужно применить к ней. Вот почему я поставил {attr_value1 ': FirstScheme, ...} в свой вопрос. – dragoon

1

Конечно, вы можете:

$schemes = [ 
    'attr_value1' => FirstScheme::$COLORS, 
    'attr_value2' => SecondScheme::$COLORS, 
    ... 
]; 

Или даже во время выполнения:

$schemes = [ 
    'attr_value1' => 'FirstScheme', 
    'attr_value2' => 'SecondScheme', 
    ... 
]; 

А потом:

$reflector = new ReflectionClass($schemes['attr_value1']); 
$schema = $reflector->getStaticPropertyValue('COLORS'); 

Но это, похоже, не любой ремонтопригодны на всех, и вы бы подобно хранению такой информации на соответствующем слое данных, без жесткого кодирования их как статических полей класса [который не является их p ЗАДАЧА].

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