Преамбюл: Лош дизайн ли е базовият клас да бъде наясно и да осъществява взаимодействия с помощта на производни типове? Предполагам, че не, така че какъв подход трябва да обмисля за следното?
(Езикът е PHP, но мисля, че този въпрос е по-загрижен за по-широкия предмет на шаблоните за проектиране)
Имах дилема, опитвайки се да моделирам набор от класове, които да действат като възли; Продължавам да предполагам моите дизайнерски решения и това води до вечно разочарование.
Предвид този набор от параметри:
- Възлите имат родителски препратки (еднопосочно преминаване)
- Всеки тип обект, извлечен от Node, може да бъде родител (или дете) на всеки друг тип обект, извлечен от Node.
Така че имам:
abstract class AbstractNode{
protected $_parent;
public function __construct(self $parent = null){
$this->_parent = $parent;
}
public function get_parent(){
return $this->_parent;
}
}
class NodeOne extends AbstractNode{ }
class NodeTwo extends AbstractNode{ }
// more derivatives
Ето къде идва моята дизайнерска дилема; по време на обхождане NodeOne
екземплярите може да се наложи да бъдат намерени, сами по себе си и всякакви други екземпляри на типове, извлечени от AbstractNode
(имайте предвид, че тази функционалност не е изключителна за NodeOne
екземпляри, но това е само пример)
Това ще позволи на специфично за тип обхождане, например, да агрегира данни от обекти от определен тип нагоре в дървото. Реших, че ще специализирам метод, който да обслужва тази цел:
public function get_node_one_ancestor(){
if($this->_parent instanceof NodeOne){
return $this->_parent;
}
if(null !== $this->_parent){
return $this->_parent->get_node_one_ancestor();
}
return null;
}
Тъй като всеки производен тип може да се наложи да премине през екземпляри NodeOne
, би имало смисъл този метод да се използва в базовия клас AbstractNode
, но сега моят базов клас изисква познаване на производен тип.
Мисля, че това мирише лошо, но не знам къде другаде трябва да отиде този метод. Чета за структурни модели за възможни решения.
Една аналогия, която идва на ум, е DOM, извършващ обхождане на предшественик за определени типове:
<root>
<foo id="1">
<bar id="2"></bar>
<bar id="3">
<foo id="4">
<bar id="5">
<foo id="6">
<bar id="7"></bar>
</foo>
</bar>
<bar id="8"></bar>
</foo>
</bar>
</foo>
</root>
От
bar[@id='8']
обобщете всичкиfoo
предшественикid
стойности:
Резултат4 1
От
bar[@id='7']
обобщете всичкиfoo
предшественикid
стойности:
Резултат6 4 1
NodeOne
от моя пример), всички възли, извикани в него, трябва да наблюдават каквито и свойства да е променил този възел, следователно трябва да премина обратно за намиране на екземпляри наNodeOne
и агрегиране/сливане на свойства, преди извикването да може да бъде завършено. Позволява среда за каскадно изпълнение. - person Dan Lugg   schedule 13.12.2011