I am encountering an example where the strategy pattern in a domain model should be used. I have a User class representing users of the system. Each user may receive requests while using the system. Upon reception of a request, some processing logics are possible:
In this case, it seems that the strategy pattern is adapted. I have an interface called RequestReceivedPolicy with multiple classes that implement this interface (i.e. one class per processing logic). The User class holds a reference on one instance of the class corresponding to the selected policy.
This seems right on the object side. My question concerns the persistence side which, in my case, is a relational database. A user selects a policy through the a management interface. I want to persist this choice so that next time the user login, this information is saved. I thought about persisting the instance hold by the User class but I don't think it's the right way, since this instance is more about logic than data.
Thanks
EDIT:
public RequestReceivedPolicy {
public boolean processRequest();
}
public IgnoreRequestPolicy implements RequestReceivedPolicy {
public boolean processRequest(){
//ignore logic
}
}
public CustomRequestPolicy {
private int someData1;
private String someData2;
public boolean processRequest(){
//custom logic that uses someData1 and someData2
}
}
The location of the policy choice persistance depends on where/how that policy gets passed in or configured into your User
class, and you didn't really ellaborate that.
If, for example, your User
class has something like this:
class User
{
// policy is passed in during ctor
public User(object otherArgs, RequestReceivedPolicy policy)
{
}
}
...then the class responsible for creating the User
would likely have to maintain that preference external to User
.
Similarly, if the User object simple holds the RequestReceivedPolicy reference like this:
class User
{
public User(object otherArgs)
{
}
public void setPolicy(RequestReceivedPolicy policy)
{
_currPolicy = policy;
}
public RequestReceivedPolicy getPolicy()
{
return _currPolicy;
}
}
...and the User
class has no way to set its own Policy object then, again, you have to rely on an external entity to persist the policy choice.
If instead the policy selection is "pulled" into the User class like this:
class User
{
public User(object otherArgs, RequestReceivedPolicyProvider policyProvider)
{
}
public void someStimulii(object criteria, ...)
{
_currPolicy = _policyProvider.getPolicy(criteria);
}
}
...or this...
class User
{
public User(object otherArgs)
{
}
public void someStimulii(object criteria, ...)
{
_currPolicy = PolicyProvider.getInstance().getPolicy(criteria);
}
}
...then the User object should persist its selection so that it can pull that policy object when it is recreated/constructed again later. In this case, it is the "criteria" that would need to be persisted, and it might be helpful if the RequestReceivedPolicy
had an additional method to return that criteria:
RequestReceivedPolicyConfig policyConfig = _currPolicy.getConfiguration();
The RequestReceivedPolicyConfig
object should be opaque to the User object, but internally perhaps be simple dictionary that supports persistance. Then the User can pass it to the persistence layer without knowing much about it. When pulling it from the persistence layer, it is used to reinstall the RequestReceivedPolicy
using the provider. At a minumum, each RequestReceivedPolicyConfig
object would contain the class identity of the RequestReceivedPolicy
.
It is possible to have a hybrid, where the Policy is pushed via set/get but the User object can also pull in a new policy via something like the above PolicyProvider.getInstance().getPolicy(criteria)
then you still allow the User object to take advantage of the RequestReceivedPolicyConfig
based approach or keep persistence external.