Avoiding instanceof in factory method - java

I'm looking for an improved solution to the following problem. I have an object, which is passed to a factory; the factory will inspect the object type, create another type, which it populates with data from the incoming object, and returns the new one.
...
public MyAbstractClass create(MyObject a) {
if (a instanceof A) {
A obj = (A) a;
return new MyAbstractClass_1 (obj.getField(), factoryField);
}
else if (a instanceof B) {
B obj = (B) a;
return new MyAbstractClass_2 (obj.getSomething(), obj.getSomethingElse(), factoryField);
}
}
Instances of the return type are treated generically afterwords. Going forward I need to support more types and if possible I'd like to avoid an instanceof solution. How can I improve this?

Can you add the create method to MyObject instead? That way you won't need instance of anymore because each instance of MyObject knows how to 'create'. You won't have a factory anymore though :(
It would look something like (assuming MyObject is an interface. if it's a class, then just extend instead):
interface MyObject {
...
public MyAbstractClass create(MyObject a);
...
}
public class A implements MyObject {
...
public MyAbstractClass create(MyObject a) {
return new MyAbstractClass_1 (obj.getField(), factoryField);
}
...
}
public class B implements MyObject {
...
public MyAbstractClass create(MyObject a) {
return new MyAbstractClass_2 (
obj.getSomething(),
obj.getSomethingElse(),
factoryField);
}
...
}

The bodies of your if statements should be virtual or abstract members on MyObject.
abstract class MyObject {
public abstract MyAbstractClass create();
}
class A extends MyObject {
#Override
public MyAbstractClass create(Object factoryField) {
return new MyAbstractClass_1 (this.getField(), factoryField);
}
}
class B extends MyObject {
#Override
public MyAbstractClass create(Object factoryField) {
return new MyAbstractClass_2 (this.getSomething(), this.getSomethingElse(), factoryField);
}
}
Generally, when you see yourself checking the type of an object to do something different depending on the concrete type, that likely means that you should be using polymorphism and the code should be going into the concrete types themselves.
Updated that the MyObject data should be coming from the current instance and not passed as a parameter, as you pointed out. Only issue is that I'm not sure where you'd put factoryField now. You could pass it as a parameter as above, and since these are virtual members you could still have a factory as well:
class SomeFactory {
private Object factoryField;
public SomeFactory(Object factoryField) {
this.factoryField = factoryField;
}
public MyAbstractClass create(MyObject a) {
return a.create(factoryField);
}
}

Related

How do I properly extend this abstract class?

Hi I'm inexperience with Java. I understand the concepts of inheritance but I think the syntax is eluding me. I'm seeking some help to get me started in extending this abstract class:
I need to create a concrete object from it.
What this class should do is take in a type during initialization and store a list of objects of that type. Sort them and then return a list of n top objects when showTopN is called.
I have not started implementing the logic yet.
abstract class Foo<T extends Comparable<T>> {
int n;
Foo(int n){ // constructor; sets object property n
this.n = n;
}
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top n entries in the list, sorted.
}
I've tried to extend this into a concrete object this way:
class ConcreteFoo extends Foo {
private List<Foo> fooList;
public void push(Foo object) {
}
#Override
public List<Foo> showTopN() {
return fooList;
}
#Override
public int compareTo(ConcreteFoo other) {
return 0;
}
}
But the compiler is complaining that I have not overridden the push method.
What is wrong?
There are two things going on here. One is the "abstractness" of Foo, but the other is the Generics. You have neglected the generics aspect.
If you know the type of object that your Concrete foo cares about, you can just use that:
class ConcreteFoo extends Foo<SomeKnownClass> {
private List<SomeKnownClass> list = new ArrayList<SomeKnownClass>();
void push(SomeKnownClass skc) {}
List<SomeKnownClass> showTopN() { return list; }
}
Now, if you don't know the type of it, you can still use generics:
class ConcreteFoo<T extends Comparable<T>> extends Foo<T> {
private List<T> list = new ArrayList<T>();
void push(T skc) {}
List<T> showTopN() { return list; }
}
Note that neither Foo nor ConcreteFoo implement Comparable, so you don't need the compareTo method.
The push method specifies that it will accept a T object, which is Foo's generic type, which you haven't declared. If you want Foo to be a List of itself, which I'm not certain that you do, you'd have to declare it as
class ConcreteFoo extends Foo<Foo> {
But I think you need to re-examine your basic principles.
You're conflating a container with the objects that it contains. The class structure that you want is something like:
class Foo implements Comparable<Foo> { ... }
abstract class GenericContainer<T> {
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top k entries in the list, sorted.
}
class FooContainer extends GenericContainer<Foo> {
private List<Foo> fooList;
...
}
Your showTopN method can then be something like:
public List<Foo> showTopN() {
return Collections.sort(fooList).subList(0, n);
}

Java factory pattern with different initialisation object types

I'm using the factory pattern to create instances, and want to initialise these instances with different objects. At the moment I'm simply casting the object, but this doesn't feel right.
public interface IGenerator {
public IGeneratedObject generate();
}
public class FirstGenerator implements IGenerator {
private List<FirstObject> list;
public FirstGenerator(List<FirstObject> list) {
this.list = list;
}
public IGeneratedObject generate() {
return doSomeStuff(list);
}
}
public class SecondGenerator implements IGenerator {
private UnrelatedObject obj;
public SecondGenerator(UnrelatedObject obj) {
this.obj = obj;
}
public IGeneratedObject generate() {
return doOtherThingsStuff(obj);
}
}
public class GeneratorFactory {
public static IGenerator createGenerator(GeneratorType type, Object object) {
switch (type) {
case FIRST:
return new FirstGenerator((List<FirstObject>) object);
case SECOND:
return new SecondGenerator((UnrelatedObject) object);
}
return null;
}
}
Usage would then be as follows:
IGenerator gen1 = GeneratorFactory.createGenerator(GeneratorType.FIRST, listOfFirstObjects);
IGenerator gen2 = GeneratorFactory.createGenerator(GeneratorType.SECOND, unrelatedObj);
FirstObject and UnrelatedObject aren't related at the moment - no common base class or interfaces.
In the factory method, the compiler of course shows an 'Unchecked cast from...' warning.
Is there a better way? It seems like a situation where generics could be used, but is this unfeasible due to the objects not being related?
Could you create factory class so that the usage would be as below?
IGenerator gen1 = GeneratorFactory.createGeneratorFirst(listOfFirstObjects);
IGenerator gen2 = GeneratorFactory.createGeneratorSecond(unrelatedObj);
There is no reason to have method "create generator".
Creating generator is encapsulated by constructor and class type itself.
Using IGenerator gen1 = new FirstGenerator((List<FirstObject>) object); is completely fine.

Reference Object Through Its Implemented Generalized Interface [duplicate]

This question already has answers here:
Java generic interfaces with typesafe implementations
(2 answers)
Closed 8 years ago.
I have a converter interface that looks something like this:
public interface MyTypeConverter<T>
{
public MyObject toMyObject(T obj);
public T fromMyObject(MyObject mo);
}
I also have an implementation of that interface:
public class ABCTypeConverter implements MyTypeConverter<ABCObject>
{
public MyObject toMyObject(ABCObject obj)
{
...do conversion...
}
public ABCObject fromMyObject(MyObject mo)
{
...do conversion...
}
}
And a factory that evaluates the objects type, and returns an appropriate converter implementation:
public class MyTypeConverterFactory
{
public static MyTypeConverter<?> create(Object source)
{
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
}
}
Now the problem I am having is in referencing the Factory's returned converter instance by using the interface:
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
The last line gives me the following compile-time error:
The method toMyObject(capture#3-of ?) in the type MyTypeConverter<capture#3-of ?>
is not applicable for the arguments (ABCObject)
So how could I reference the converter in a generic fashion?
EDIT
The core of my question is: How do I call a method on an interface reference without first casting to the underlying concrete type? And if I can't, then what is the point of creating a generic interface to begin with? I.E., How do I do this (regardless of how I get the reference):
MyTypeConverter<?> converter = MyTypeConverterFactory.create(someObject);
MyObject mo = converter.toMyObject(someObject);
Without first casting "converter" to its underlying concrete type?
This is a total anti-pattern approach to the FactoryMethod Pattern:
if ( source instanceof ABCObject )
return new ABCTypeConverter();
...and so on...
Don't do that it will never scale and will never be maintainable.
What is wrong with:
TypeConverter<ABCObject> tc = new TypeConverter<ABCObject>();
That is how every sane framework that implements something like this works.
For example:
com.google.common.base.Converter
Look at the how Jackson does it for JSON Serializer/Deserializers as well.
There is a way with Guava to get an instance of a type T
Class<T> klass = (Class<T>) new TypeToken<T>(getClass()) {}.getRawType();
Then you can do klass.newInstance(); but this is hacky was well.
You can try with Polymorphism as well instead of making it Generic.
Just return the interface reference instead of actual object reference from factory's create() method. At run-time the actual object decide what method should be called based on overridden method logic.
In below sample code I have created an interface MyTypeConverterObject that is implemented by all the classes that are part of MyTypeConverter interface.
Now simply return MyTypeConverterObject from factory's create() method.
Sample code:
interface MyTypeConverterObject {}
class ABCObject implements MyTypeConverterObject {}
class XYZObject implements MyTypeConverterObject {}
class MyObject {}
interface MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj);
public MyTypeConverterObject fromMyObject(MyObject mo);
}
class ABCTypeConverter implements MyTypeConverter {
public MyObject toMyObject(MyTypeConverterObject obj) {
return new MyObject();
}
public MyTypeConverterObject fromMyObject(MyObject mo) {
return new ABCObject();
}
}
class MyTypeConverterFactory {
public static MyTypeConverter create(Object source) {
if (source instanceof ABCObject) {
return new ABCTypeConverter();
}
return ...;
}
}
A Factory method should return product of same type i.e. product that implements same interface.
For example: A car factory can return cars of different type but can't produce bike.
If you need to return different type of products then use Abstract factory.

Create generic Interface restricted to own class

I would like to create a generic interface for those two classes but I'm not sure how to specify the generics the right way.
public class ThingA implements Thing {
public ThingA createCopy(ThingA original);
}
public class ThingB implements Thing {
public ThingB createCopy(ThingB original);
}
I tried it this.
public interface Thing<V extends Thing<V>> {
public V createCopy(V original);
}
But I'm still able to do things like this, which shouldn't be allowed.
public class ThingB implements Thing<ThingA> {
public ThingA createCopy(ThingA original);
}
There is no this key-word generics (nor for methods parameters and return values declaration) and thus you cannot do exactly what you want.
In other words the interface will permit to ensure all the methods in the class use consistent types, but not to reference the class type itself.
This is not possible. And it is not what Generics is for. Generics is for type safety, i.e. avoiding casts. If someone makes a class ThingB that implements Thing<ThingA> somehow, then great. It is perfectly type-safe. Why do you care? How does it impede what you are doing?
Are you looking for
public interface Thing<V> {
public V createCopy(V original);
}
? If not, can you explain in more detail what it means to you to "create a generic interface for two classes"?
In case you are free to use extension instead of implementation, then you could do that this way:
public interface Thing { ... }
public abstract class Copyable {
public final Copyable copy() {
Copyable clone = createCopy();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return clone;
}
protected abstract Copyable createCopy();
}
And then use it like:
public class Test extends Copyable implements Thing {
public String content = null;
#Override
public Copyable createCopy() {
Test clone = new Test();
clone.content = this.content;
return clone;
}
}
/*code somewhere*/ {
Test t1 = new Test();
t1.content = "Hello world!";
Test t2 = (Test)t1.copy();
System.out.println(t2.content);
}
One problem with this, is that Copyable is not an interface. However, this can be used without much pain, as seen in the example, but the class checking used is not supported on the language level. With other words, the createCopy abstract method is not restricted to the class it copies, and all that is up to the programmer who extends the Copyable class, or a class, which extends it.
The positive side, is that if you call the .copy() on the object, it must return an object same as itself. Instead of an exception you can return null, if you want. Then you got good or nothing.
But, to be honest, I don't really understand, why your createCopy local method has a parameter.
It could be then a static method ... altrough I cannot even imagine what would go into that code block:
static <X extends Thing> X copy(X object) { ... }
May you could combine the pratice with a static generic method and the result becomes a bit more friendly:
public interface Thing extends Cloneable {
public static <X extends Thing> X copy(X thing) {
Object clone = thing.clone();
if (clone.getClass() != getClass())
throw new RuntimeException("Copy has wrong type!");
return (X)clone;
}
}
public class ThingA implements Thing {
public Object clone() { ... }
}
/*code somewhere*/ {
ThingA a1 = new ThingA();
ThingA a2 = Thing.copy(a1);
}
Still, the cloning method is regulated by an exception instead of language restriction, but I think this is far the best solution.

Member type with multiple bounds

So I just learned that I can
public <T extends SomeClass & SomeInterface<OtherClass>> doSomething(T foo);
in Java to express that foo extends SomeClass and also implements SomeInterface<OtherClass>. So far, so good.
But how would I assign foo in doSomething() to a member variable? The class of course does not know anything of the type definition that is attached to the doSomething() method.
The context where I need this is a POJO whose constructor needs to be argumented with said T and that needs to return the said T again.
The closest I came was the following:
public class ThisClass implements AnotherInterface<AnotherClass> {
private final Object obj;
public <U extends SomeClass & SomeInterface<AnotherClass>> ThisClass(U obj) {
this.obj = obj;
}
public <U extends SomeClass & SomeInterface<AnotherClass>> U getObject() {
return (U) obj;
}
}
but I'm unable to wind my head around to get a solution without the unchecked cast.
Can't you make the class generic:
public class ThisClass<U extends SomeClass & SomeInterface<AnotherClass>>
implements AnotherInterface<AnotherClass> {
private final U obj;
public ThisClass(U obj) {
this.obj = obj;
}
public U getObject() {
return obj;
}
}
and use it like this:
ThisClass<String> instance = new ThisClass<>("Foo");
String value = instance.getObject();
Unfortunately, it can't be done. The problem is Java doesn't have denotable interception type A&B.
If Java has that, we can write something like
Pet&Furry pet;
void set(Pet&Furry pet){ this.pet=pet; }
Pet&Furry get(){ return pet; }
Now, type variables can have interception bounds A&B, so one would think we can exploit that
Object pet;
<U extends Pet&Furry> void set(U pet){ this.pet=pet; }
<U extends Pet&Furry> U get(){ return (U)pet; }
But it's not type safe. Consider
x.set(dog);
...
Cat cat = x.get();
we may live with that risk if we require programmers to mentally keep track of the actual type.

Categories

Resources