I have a list of Registration
's, on which I need to apply a set of rules to each individually.
Rules can be a single Rule
, or a sequence of rules, representable by a tree. One rule is a ConditionalRule
, where the condition itself can be a tree (e.g. and,or,not, isOwnedByAdmin), which checks if a specific condition apply to the given Registration
. I have used the composite pattern on both Rule
and Conditional
, which currently recieves the registration like:
$rule->apply($registration)
or conditionally:
if($condition->check($registration))
{
$rule->apply($registration)
}
This works, but needs to be more flexible in the future.
Eventually, I will have to apply this method on something which is not a Registration
, say a Post
object instead. Post
should be able to be run through this rule tree similarly, on compatible rules and conditions. For example, both could check the condition isOwnedByAdmin
, but only Post
is compatible with the rule PublishPost
. I'm ok with the fact that I will be able to construct an illegal tree (something not able to run on a Registration
because it requires a Post
).
I could extend my composit interfaces:
interface Rule
{
public function applyTo(Registration $registration, Env $environment);
}
interface Condition
{
public function check(Registration $registration);
}
into:
interface Rule
{
public function applyToRegistration(Registration $registration, Env $environment);
public function applyToPost(Post $post, Env $environment);
}
interface Condition
{
public function checkRegistration(Registration $registration);
public function checkPost(Post $post);
}
In the end, I will have quite a few (10+) Condition
classes, many Rule
classes and few types of objects it will need to run over (3-10). I would have to modify all those classes whenever I need a new type to check against.
I'm considering using 2 instances of the visitor pattern. A ConditionVisitor
and a RuleVisitor
. The RegistrationRuleVisitor
would be created with a Registration
object and a RegistrationConditionVisitor
visit the Rule
tree with.
But as my composit trees is "actions", applied to a resource, I'm not sure the visitor pattern applies at all? As I'm visiting something which cannot be evaluated without input (a registration/post). Or is there another pattern that I have missed which allows me to use the same tree based application of methods upon an object?
Post
and aRegistration
. Is the implementation the same for each or are you going to have different logic in thePost
andRegistration
methods?