remove duplication
I have a class contains 10 methods which are doing almost the same things apart from one key event. Two examples are given below:
Public String ATypeOperation(String pin, String amount){ doSomething(); doMoreStuff(); requestBuilder.buildATypeRequest(pin, amount); doAfterStuff(); }
Public String BTypeOperation(String name, String sex, String age){ doSomething(); doMoreStuff(); requestBuilder.buildBTypeRequest(name, sex, age); doAfterStuff(); }
As you can see from the above methods, they are similar apart from calling different methods provided by requestBuilder. The rest 8 are similar too. There is a lot duplicated code here. I feel there is a better way to implement this, but don’t know how. Any idea开发者_Go百科s and suggestions are appreciated.
Thanks, Sarah
Use something like RequestBuilder
, that accepts all these kinds of parameters:
public RequestBuilder {
// setters and getters for all properties
public Request build() {
doStuff();
Request request = new Request(this);
doAfterStuff();
return request;
}
}
and then
new RequestBuilder().setAge(age).setName(name).build();
What’s the nearest substitute for a function pointer in Java?
Function Pointers in Java
interface RequestBuilder {
void doStuff(params);
}
public RequestBuilder getARequestBuilder() {
return new RequestBuilder() {
void doStuff(params) {
// impl.details
}
}
}
public RequestBuilder getBRequestBuilder() {
return new RequestBuilder() {
void doStuff(params) {
// impl.details
}
}
}
public String buildRequest(yourParams, RequestBuilder builder){
doBefore();
builder.doStuff(yourParams);
doAfter();
}
I think this is called the Strategy pattern. It looks a lot like the Command pattern but because you encapsulate an algorithm it seems to be Strategy :)
What Bozho suggest is the Builder pattern.
I recommend you browse through a list of patterns some time, or buy Head First Patterns. Really fun reading.
You could pass the builder object to a generic buildRequest method. Since not only the algorithm but also the arguments vary, i put them into the builder. I dont think thats a nice solution but i wanted to show a command pattern here :D (Extraneon showed how to decouple params and command)
// call somewhere in the code:
Builder b = new BTypeBuilder();
b.age = "20"; b.sex = "female"; b.name = "eve";
String res = buildRequest(b);
Public String buildRequest(Builder builder)
{
doSomething();
doMoreStuff();
builder.build();
doAfterStuff();
}
// Command pattern
class BTypeBuilder implements Builder
{
String name, age, sex;
// Constructor here
void build()
{
// Do your stuff here
}
}
class ATypeBuilder implements Builder
{
String pin, amount;
// Constructor here
void build()
{
// Do your stuff here
}
}
public interface Builder
{
void build();
}
In addition to other answers, this might also be useful for you (If you want to just plugin your method, not using your parameters for 'before' and 'after' methods)
interface Function0<R> {
R apply();
}
public void performOperation(Function0<Void> operation) {
doSomething();
doBeforeStuff();
operation.apply();
doAfterStuff();
}
then you could use it like this,
final RequestBuilder builder = new RequestBuilder();
performOperation(new Function0<Void>() {
public Void apply() {
builder.buildATypeRequest("1234", "2445");
return null;
}
});
performOperation(new Function0<Void>() {
public Void apply() {
builder.buildBTypeRequest("1234", "2445", "1234");
return null;
}
});
Instead of sending a long parameter list just push all the parameters in a map and send that map as argument.
精彩评论