Victor Axelsson
Victor Axelsson

Reputation: 1466

Design pattern - different object in, same object returned

I'm working on a Android Java project and I have hunch that I will be able to use a better pattern for a situation that accures in two places.

I have a class wich builds ContentValues (basically key/value object) from a inputed model/object and returns a ContentValue object which have different key/values depending on which object I'm inputing.

Currently, there is a method for each object I want to generate ContentValues for. E.g:

public ContentValues BuildPage (Page p){
ContentValues val = new ContentValues(); 
val.put(PAGE_DESCRIPTION, p.getDesciption()); 
val.put(PAGE_DISPLAYABLE, BitmapHelper.ConvertToBlob(p.getPic())); 
val.put(PAGE_MODULE_ID, p.getModuleId()); 
val.put(PAGE_TITLE, p.getTitle()); 
return val; 

}

public ContentValues BuildQuestion(Question q){
ContentValues val = new ContentValues(); 
val.put(QUESTION_CORRECT, q.getCorrect());
val.put(QUESTION_QUESTION, q.getQuestion()); 
val.put(QUESTION_QUIZ_ID, q.getQuizId()); 

return val; 

}

My intuition tells me that there probably is a better way of doing it.

The second situation is almost the opposite. I input the same object, builds different objects and returns them. E.g:

   public Quiz BuildQuizObj(Cursor c){
            //{QUIZ_ID, QUIZ_MODULE_ID}; 
            Quiz q = new Quiz(); 

            if(CursorIsOk(c)){
                c.moveToFirst(); 
                q.setId(c.getLong(0)); 
                q.setModuleId(c.getLong(1));
            }

            return q; 
        }


    public Module BuildModuleObj(Cursor c){
        List<Module> modules = BuildModulesObj(c); 

        Module m = new Module(); 
        if(modules.size() > 0){
            m = modules.get(0);
        }

        return m; 
    }

So my question is: Is there any design pattern I can use to make the same functionality in a more generalized way so I can use the same method instead of creating new methods for each new object i want to use?

Upvotes: 1

Views: 1416

Answers (1)

ElDuderino
ElDuderino

Reputation: 3263

You can use interfaces and generics, e.g. like this :

Edit: Old stuff at bottom!

public interface Buildable {

    public ContentValues values();

}

public interface Builder<S, T extends Buildable> {

    public T build(S source);

}

public class Module implements Buildable {

    @Override
    public ContentValues values() {
        ContentValues c = new ContentValues();
        c.put("name", getClass().getName());
        return c;
    }

}

public class ModuleFromCursorBuilder implements Builder<Cursor, Module> {

    @Override
    public Module build(Cursor source) {
        return new Module();
    }

}

public class QuizFromCursorBuilder implements Builder<Cursor, Quiz> {

    @Override
    public Quiz build(Cursor source) {
        return new Quiz();
    }

}

Cursor cursor = null;
Log.i("ModuleFromCursorBuilder",new ModuleFromCursorBuilder().build(cursor).values().get("name")+"");
Log.i("QuizFromCursorBuilder",new QuizFromCursorBuilder().build(cursor).values().get("name")+"");

...now you could generalize your S and T even more, more interfaces... endless story.

---- Old Stuff ----

public interface Buildable<T> {
    public T build(Cursor c);
}

public class ModuleBuilder implements Buildable<Module>{

    @Override
    public Module build(Cursor c) {
        return new Module();
    }

}

public class QuizBuilder implements Buildable<Quiz>{

    @Override
    public Quiz build(Cursor c) {
         return new Quiz();
    }

}

Now you just call one method, build, and you get the object.

You also do it like this with your first problem...

public interface Valuable {

    public ContentValues values();

}

public class Question implements Valuable {

    @Override
    public ContentValues values() {
        return new ContentValues();
    }

}

public class Page implements Valuable {

    @Override
    public ContentValues values() {
        return new ContentValues();
    }

}

Here you just call values() on your object and it retrieves the correct ContentValues.

Upvotes: 2

Related Questions