2

I have two Classes, with very similar behaviors, both from a third party library. Both needs to be populated with some value object and sent to specific queues in order for logging. Please note both of them does not have a common parent.

I am scratching my head to find out ways to refactor this. Here is the sceanrio.

Class 1 : Apple Class 2 : Orange

Unfortunately, Apple and Orange are not child classes of Fruit And I can not change them to extend a base class. Constructors of Apple and Orange have different signatures.

Current code:

if(isApple){
    Apple apple = new Apple(....);
    apple.setColor(Color.RED);
    apple.setPrice(10);
    apple.setCount(1000);

    AppleMQObject applMQObject = new AppleMQObject(apple);
    Producer appleProducer = Factory.create("apple-producer");
    appleProducer.send(applMQObject);
}else{
    Orange orange = new Orange(...);
    orange.setColor(Color.ORANGE);
    orange.setPrice(30);
    orange.setCount(100);
    OrangeMQObject oMQObject = new oMQObject(orange);
    Producer orangeProducer = Factory.create("orange-producer");
    orangeProducer.send(orangeMQObject);
}

I can move the MQ code out to a common method. But how to handle the apple/orange situation.

  • 2
    What's your goal for the refactoring? I can see that you might want to avoid writing too many copies of the two blocks shown in your question, but unless there are lots more object types that you want to abstract away, it doesn't seem like a very pressing problem. – Mike Partridge Oct 2 '13 at 16:15
  • 2
    Are you trying to achieve a single queue for all 'Fruit' objects? – c_maker Oct 2 '13 at 16:15
  • 4
    This question is language specific - is this Java? C#? Anything else? In C++, you could solve this easily using templates; in C# this won't work with generics because the classes at stake would at least need a common interface. – Doc Brown Oct 2 '13 at 16:17
  • .. in C#, one could create an (ugly) reflection hack, and I guess something similar is possible with Java, too. – Doc Brown Oct 2 '13 at 16:23
  • What are the parameters passed to the Apple and Orange constructors? – Aaron Kurtzhals Oct 2 '13 at 16:27
3

This is a refinement of @user2670177 answer:

If the function signatures of both are nearly the same it might be easier to use inheritance instead of composition.

Given you have Oranges and Appels you want to process

class Orange {
    public void setColor(Color color){}
    public void setPrice(int euroCents){}
    public void setCount(int numberOfItems){}
}

class Apple {
    public void setColor(Color color){}
    public void setPrice(int euroCents){}
    public void setCount(int numberOfItems){}
}

You can define a common interface for both

interface MyFruitInterface{
    void setColor(Color color);
    void setPrice(int euroCents);
    void setCount(int numberOfItems);
}

and attach the interface to the inherited class

class MyOrangeImpl extends Orange implements MyFruitInterface {
} 

class MyAppleImpl extends Apple implements MyFruitInterface {
} 

Now your common code MQObject can handle both:

class MQObject {
    private MyFruitInterface fruit;
    MQObject(MyFruitInterface fruit) {
        this.fruit = fruit;
    }

    void setPriceColorCount(int euroCents, Color color, int numberOfItems) {
        fruit.setPrice(euroCents);
        fruit.setColor(color);
        fruit.setCount(numberOfItems);
    }
}

void testMQ() {
    MQObject applMQObject = new MQObject(new MyAppleImpl());
    MQObject orangeMQObject = new MQObject(new MyOrangeImpl());
}
2
MyFruitInterface{
setColor();
setPrice;
..
}

MyOrangeImpl{
Orange o;

MyOrangeImpl(Orange o)
{
this.o = o;
}
setColor(Color C){
o.setColor(c);
}
setPrice(int price){
o.setPrice(price);
}
..
} 
MyAppleImpl{

Apple a;

MyAppleImpl(Apple a)
{
this.a = a;
}
setColor(Color C){
a.setColor(c);
}
setPrice(int price){
a.setPrice(price);
}
..
} 

Now you have a common interface;

  • how does this answer the question asked? – gnat Oct 3 '13 at 6:33
  • +1 for using a common interface. For more Details see Adapter_pattern – k3b Oct 3 '13 at 13:44
  • 2
    -1 for code with no explanation of what it's doing. @k3b's answer is a great example of how to explain code like this. – Bobson Oct 3 '13 at 13:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.