I have a helper class which has a method that perform some checks against a field in a model. I have two models, ModelA and ModelB, they have some similarities but not all. One of them is they both have a field, lets say string ProductCheckField. The ProductCheckMethod returns back the Model, because of that it has created duplication of methods which does the same thing but returns a different model. Even the extracted methods are duplicates. Is there a good design pattern or any other good practice/technique I can use to eliminate duplication of having to create two methods?
N.B I can't use a shared Interface as the models are not the same.
Currently I have..
public class ModelA
string blah..
int blah
.....
string ProductCheckField
public class ModelB
string xyz
int xyz
.....
string ProductCheckField
public class HelperClass
{
public ModelA ProductCheckMethod(ModelA model)
{
/// do somthing
performX(model);
checkY(model);
return model;
}
public ModelB ProductCheckMethod(ModelB model)
{
/// do somthing
performXDuplicate(model);
checkYDuplicate(model);
return model;
}
}
4 Answers 4
What you have shown of the Models shows the same interface. So your protestations of differences are unsupported by the example you give. I suggest you wrap the fields you check in performX and checkY with accessor methods that are commonly named across model A and B and extract a common interface for the use of your Helper class.
public interface CheckModel
{
public String getStringValue();
public void setStringValue(String blahs);
public int getIntValue();
public void setIntValue(int blah);
public String getProductCheckField();
public void setProductCheckField(String productCheckField);
}
public class ModelA implements CheckModel
{
String blahs;
int blah;
String ProductCheckField;
public String getStringValue()
{
return blahs;
}
public void setStringValue(String blahs)
{
this.blahs = blahs;
}
public int getIntValue()
{
return blah;
}
public void setIntValue(int blah)
{
this.blah = blah;
}
public String getProductCheckField()
{
return ProductCheckField;
}
public void setProductCheckField(String productCheckField)
{
ProductCheckField = productCheckField;
}
}
public class ModelB implements CheckModel
{
String xyzs;
int xyz;
String ProductCheckField;
public String getStringValue()
{
return xyzs;
}
public void setStringValue(String xyzs)
{
this.xyzs = xyzs;
}
public int getIntValue()
{
return xyz;
}
public void setIntValue(int xyz)
{
this.xyz = xyz;
}
public String getProductCheckField()
{
return ProductCheckField;
}
public void setProductCheckField(String productCheckField)
{
ProductCheckField = productCheckField;
}
}
public class HelperClass
{
public CheckModel ProductCheckMethod(CheckModel model)
{
/// do somthing
performX(model);
checkY(model);
return model;
}
private void checkY(CheckModel model)
{
// ...
}
private void performX(CheckModel model)
{
// ...
}
}
You seem to have some sort of mental block going on. If you want a design that eliminates the duplication, you're going to have to change your design somehow, which you seem resistant to do. You need to look past your current design.
Some ways to eliminate the duplication, some of which are better than others:
- Put the common stuff of the models into a common class, with your models containing a reference to that object, as Telastyn suggested in the comments.
- Reverse of Telastyn's suggestion, where you have a
ProductCheckStuff
class, with pointers inside it to one of the models. - Use generics in
HelperClass
or its methods, with the model as the generic parameter. - Have each model implement an interface with getters for the fields you need.
- Extend the model from a base class that implements the
ProductCheckMethod
. - Put the product check fields and methods into a mixin (if your language supports it) that is mixed in with the other fields of your model.
You can't make an omelette without breaking some eggs. You have a ton of choices here. Keep trying them until you find one that works.
It's hard to understand fully what you need done here. It looks like you MIGHT have a case for the Visitor pattern but you said you can't use the same interface.
The only other alternative would be the Strategy pattern where the CheckMethod would be implemented in a strategy class for each Model and instead of the overloaded methods you can use generics to map the Model to the strategy.
public class HelperClass
{
public T CheckMethod(T model)
{
var strategy GetStrategyFor(typeof(T));
var result = strategy.Execute(model);
return result;
}
}
You could use an IoC container or other methods for determining how a type maps to a given strategy. But once you've done that, you can add new models and matching strategies to your heart's content.
With the constrints you having (unable to use a common interface) for ModelA and for ModelB, there isn't a lot of things you can do from the Models. However you could generalize the helper class.
One way to do is,
public class RequestDTO
{
string xyz_blah;
}
public class ResultDTO.
{
string ProductCheckField;
}
public class HelperClass
{
public static ResultDTO ProductCheckMethod(RequestDTO request)
{
//do something
ResultDTO result = performXUsingRequestData(model);
checkYUsingRequestData(model,result);
return result;
}
}
Here the data you currently sending to the methods performX,checkY are added to the RequestDTO and whatever the data you want to update on the model are added to the ResultDTO.
In your model you could call the helper class like this,
public class ModelA
{
string blah..
int blah
.....
string ProductCheckField
public void ProductCheckMethod()
{
RequestDTO dto = new RequestDTO { xyz_blah = blah; }
ResultDTO result = HelperClass.ProductCheckMethod(dto);
ProductCheckField = result.ProductCheckField;
}
}
Same goes for the ModelB
Explore related questions
See similar questions with these tags.
ModelA
andModelB
have duplicate checks, why are the duplicate bits not shared in some third class?check(modelA.X); check(modelA.Y)
,check(modelB.X); check(modelB.Y)
and the such. Without more concrete examples, it's hard to say.