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
Conditional, which currently recieves the registration like:
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
I could extend my composit interfaces:
public function applyTo(Registration $registration, Env $environment);
public function check(Registration $registration);
public function applyToRegistration(Registration $registration, Env $environment);
public function applyToPost(Post $post, Env $environment);
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
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?