Implementing a generic factory - java

I am trying to design a factory for a pluggable interface. The idea is that once you have your factory instance, the factory will return the appropriate subclasses for that particular implementation.
In this case, I am wrapping a third party library that uses a String to represent an ID code, rather than subclasses. Therefore, in the implementation that wraps their library, every implementation class has a method getCode() that is not explicitly required by the interface API. I am using an enum to store this mapping between codes and interface classes.
In nearly all cases, the getCode() method is not needed. However, in just a few situations in the implementation package, I need access to that method. Therefore, my problem is that I would like to have the Factory implementation's signature tell callers that the getCode method exists if they have a reference to the specific Factory implementation.
What follows is a lot of code in my best-effort attempt to digest the situation into an sscce. I know it's very long, but it's simpler than it seems, and one of the words in sscce is "complete".
Public API:
public interface Factory {
public <T extends IFoo> T makeIFoo(Class<T> klass);
}
public interface IFoo {
void doSomething();
}
public interface IFooBar extends IFoo {
void doBarTask();
}
public interface IFooBaz extends IFoo {
void doBazTask();
}
Sample use case:
public class SomeClass {
private Factory myFactory;
public void doSomething() {
IFooBar ifb = myFactory.create(IFooBar.class);
}
}
SSCCE version of implementation:
interface ICode {
String getCode();
}
abstract class BaseCode implements IFoo, ICode {
private String code;
BaseCode(String code) {
this.code = code;
}
#Override
public String getCode() {
return code;
}
#Override
public void doSomething() {
System.out.println("Something");
}
}
class FooBarImpl extends BaseCode implements ICode, IFooBar {
FooBarImpl(String code) {
super(code);
}
#Override
public void doBarTask() {
System.out.println("BarTask");
}
}
class FooBazImpl extends BaseCode implements ICode, IFooBaz {
FooBazImpl(String code) {
super(code);
}
#Override
public void doBazTask() {
System.out.println("BarTask");
}
}
Enum codemapper:
static enum CodeMap {
FOOBAR ("A", IFooBar.class) {
FooBarImpl create() { return new FooBarImpl(getCode()); }
},
FOOBAZ ("B", IFooBaz.class) {
FooBazImpl create() { return new FooBazImpl(getCode()); }
};
private static Map<Class<? extends IFoo>, CodeMap> classMap;
static {
classMap = new HashMap<Class<? extends IFoo>, CodeMap>();
for(CodeMap cm : CodeMap.values()) {
classMap.put(cm.getFooClass(), cm);
}
}
private String code;
private Class<? extends IFoo> klass;
private CodeMap(String code, Class<? extends IFoo> klass) {
this.code = code;
this.klass = klass;
}
String getCode() {
return code;
}
Class<? extends IFoo> getFooClass() {
return klass;
}
static CodeMap getFromClass(Class<? extends IFoo> klass) {
return classMap.get(klass);
}
abstract BaseCode create();
}
Sample use case within implementation package:
public class InternalClass {
CodeFactory factory;
public void doSomething() {
FooBarImpl fb = factory.makeIFoo(IFooBar.class);
}
}
Attempt at factory:
This does not specify that the return will always implement ICode. But the passed-in interface class DOESN'T implement ICode, that's the whole point.
class CodeFactory implements Factory {
#Override
public <T extends IFoo> T makeIFoo(Class<T> klass) {
CodeMap map = CodeMap.getFromClass(klass);
if (map == null) return null; // Or throw an exception, whatever, SSCCE
return (T) map.create();
}
}
What should I do?

I realized I was making this too complicated. If I'm going to implement a factory method for each enum instance, I may as well just have separate factory methods for each interface.
public interface Factory {
IFooBar createFooBar();
IFooBaz createFooBaz();
}
class CodeFactory implements Factory {
public FooBarImpl createFooBar() {
// etc.
}
}
Of course now I have to change the Factory API if there are ever new interfaces, but I expect that will be rare.

A possible solution would be defining a wrapper that implements IFoo and the getCode() method, and your method would return the intended class in one of such wrappers.
If the wrapped instance has a getCode implemented, the wrapper would return its value, return it, otherwise return null.

Related

Handle duplicate code in concrete implementations of an interface in Spring boot application

I am working on a spring boot application, where I have an interface I as follows:
public interface I {
String getType();
void f1();
}
There are two classes implementing interface I as follows:
#Component
class A implements I {
private final MyRepo1 myRepo1;
private final Helper helper;
public A(MyRepo1 myRepo1, Helper helper) {
this.myRepo1 = myRepo1;
this.helper = helper;
}
#Override
public String getType() {
return "type1";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type1 specific handling here
}
}
One more class B implementing interface I as follows:
#Component
class B implements I {
private final MyRepo2 myRepo2;
private final Helper helper;
public B(MyRepo2 myRepo2, Helper helper) {
this.myRepo2 = myRepo2;
this.helper = helper;
}
#Override
public String getType() {
return "type2";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type2 specific handling here
}
}
Helper is as follows:
#Component
class Helper {
public int f1(String type) {
...
}
}
I have a factory class as follows, that is used to fetch an object of the appropriate type:
#Component
public class ServiceFactory {
private final Map<String, I>
typeToClassMap = new HashMap<>();
public ServiceFactory(List<I> components) {
for(I component : components) {
typeToClassMap.put(component.getType(), component);
}
}
}
This ServiceFactory is basically used to get objects according to the type.
Now, the problem is, here for sake of simplicity I have just shown two classes implementing the interface. But actually, I have a lot more classes than this, implementing the interface I.
Some of the classes may have the same implementation of f1(), resulting in duplicate code.
I cannot make f1() as the default method in interface I as this requires the dependent bean.
I cannot understand what is the best way to handle this.
Could anyone please help here?

Abstract class constructor param vs. abstract method for final data

What are the pros/cons of using the abstract class constructor vs. an abstract method for passing final data to an abstract class?
Pass via constructor:
public abstract class MyAbstractClass<T> {
private final String type;
private final Function<String, T> factoryFn;
protected MyAbstractClass(String type, Function<String, T> factoryFn) {
this.type = type;
this.factoryFn = factoryFn;
}
public T doSomething(String value) { ... }
}
Pass via abstract method:
public abstract class MyAbstractClass<T> {
abstract String getType();
abstract T getFactoryFn(String value);
public T doSomething(String value) { ... }
}
I'm aware that the abstract methods can potentially be misused, because it doesn't enforce to always return the same value.
But apart from that, is it just a matter of personal preference, or are there any real (dis)advantages for using one over the other?
I hope I am understanding your question correctly..
Usually, when a property of a class is always held in a field, it is more concise to use an abstract constructor. For example, consider the two following scenarios....
// Scenario 1:
abstract class AClass {
final int field;
public AClass(int f) {
field = f;
}
public int getField() {
return field;
}
}
class Class1 extends AClass {
public Class1(int f) {
super(f);
}
// Class Unique Code...
}
class Class2 extends AClass {
public Class2(int f) {
super(f);
}
// Class Unique Code...
}
// Scenario 2:
abstract class AClass {
public abstract int getField();
}
class Class1 extends AClass {
final int field;
public Class1(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
class Class2 extends AClass {
final int field;
public Class2(int f) {
field = f;
}
#Override
public int getField() {
return field;
}
// Class Unique Code...
}
Scenario 1 is shorter since the getter logic for field only needs to be specified once. Whereas in scenario 2, the getter logic must be overridden by both subclasses. I find scenario 2 to be redundant... why write the same code twice when you can use java inheritance to your advantage.
As a final note, I usually don't hold functions in fields unless totally necessary. Whenever you have a function in a field, it's usually a sign that an abstract function can be applied.
Here is your original code with my advice applied...
public abstract class MyAbstractClass<T> {
private final String type;
protected MyAbstractClass(String t) {
type = t;
}
protected abstract T applyFactoryFunction(String value);
public T doSomething(String value) { ... }
}
Hope this helped!

how to create an interface around classes that already exist but cannot be modified in java

Suppose I already have 2 classes in my code:
class SomeOrder {
String getOrderId() { return orderId; }
}
class AnotherOrder {
String getOrderId() { return orderId; }
}
How to create an interface around both these classes which is:
interface Order {
String getOrderId();
}
Ideally, I would modify the code so that SomOrder implements Order and AnotherOrder implements Order but the catch here is that they belong in a package that I cannot control or edit (i.e. they come from an external jar).
My algorithm currently looks like this:
void sorter(List<SomeOrder> orders) {
... <custom sort logic> ...
someOrder.getOrderId();
}
void sorter(List<AnotherOrder> orders) {
... <custom sort logic> ...
someOrder.getOrderId();
}
With a single interface I can write:
void sorter(List<Order> orders) {
... <custom sort logic> ...
order.getOrderId();
}
You can use adapter classes:
class SomeOrderAdapter implements Order {
private SomeOrder delegate;
#Override
public String getOrderId() {
return delegate.getOrderId();
}
}
and similar for AnotherOrder.
Since your interface is a functional interface, you could define functions that map to this new Order interface my referencing the getOrderId method for each different class:
private Order wrap(SomeOrder obj) {
return obj::getOrderId;
}
private Order wrap(AnotherOrder obj) {
return obj::getOrderId;
}
An example calling it:
private void test() {
List<Order> orders = Arrays.asList(
wrap(new SomeOrder()),
wrap(new AnotherOrder())
);
sorter(orders);
}
Create a Proxy wrapped around the instances implementing the interface you need. The proxy just calls the instance's method with the same parameters.
public class Proxied<T> implements InvocationHandler {
private final T wrapped;
public Proxied(T wrapped) {
this.wrapped = Objects.requireNonNull(wrapped);
}
public T getWrapped() {
return wrapped;
}
public <I> Class<I> proxy(Class<I> interfaceClass) {
#SuppressWarnings("unchecked")
Class<I> proxyClass = (Class<I>) Proxy.getProxyClass(getClass().getClassLoader(), interfaceClass);
return proxyClass;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(wrapped, args);
}
}

data access object pattern with abstract factories, creation over generic types

I'm developing a database application for android devices.
First thing I need to do is creating the data access layer.
For this I want to use DAO-Pattern with abstract factories.
For all DAOs i have one Interface witch contains the declaration that all data object needs to implement. (in my case: IDataObject)
The specific DAOs are all represented by its own interface, extending the base interface of all DAOs.
base interface:
public interface IDataObject {
public IDataId getId();
public void write() throws MyDataWriteException;
public void validate() throws MyDataValidException;
}
a extensions:
public interface IDataSample1 extends IDataObject {
public void setNotice(String notice);
public String getNotice();
public void setDate(Date date);
public Date getDate();
}
To create an data object I want use abstract to use abstract factories, something like:
public interface IDataFactory<Template extends IDataObject> {
public List<Template> getAll();
public Template get(IDataId id);
public List<Template> getList(DataAccessArgument arg);
public List<Template> getList(List<DataAccessArgument> argList);
}
and the implementation:
public class DataSample1Fac implements IDataFactory<IDataSample1> {
public DataSample1Fac () {
}
public List<IDataSample1> getAll() {
return null;
}
public IDataSample1 get(IDataId id) {
return null;
}
public List<IDataSample1> getList(DataAccessArgument arg) {
return null;
}
public List<IDataSample1> getList(List<DataAccessArgument> argList) {
return null;
}
}
I don't get any error so far, but now I want to implement an factory builder:
public class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static<T extends IDataObject> IDataFactory<T> getFactory(){
if (T instanceof IDataSample1)
return new DataSample1Fac();
return null;
}
}
I get following errors(line 8):
T cannot be resolved to a variable
and (line 9)
Type mismatch: cannot convert from DataSample1Fac to IDataFactory<T>
Don't know how to fix this, any suggestions?
I would refactor Your's DataFactoryBuilder to something like that:
class DataFactoryBuilder {
private DataFactoryBuilder() {
}
public static IDataFactory<? extends IDataObject> getFactory(Class<? extends IDataObject> clazz){
if (IDataSample1.class.isAssignableFrom(clazz)) {
return new DataSample1Fac();
}
return null;
}
}
I got following solution:
public static <T extends IDataObject> IDataFactory<T> getFactory(Class<T> type) {
if (IDataSample1.class.isAssignableFrom(type)) {
DataSample1Facfac = new DataSample1Fac();
return (IDataFactory<T>) fac;
}
}
but i get an warning on: return (IDataFactory) fac;
Type safety: Unchecked cast from DataSample1Fac to IDataFactory<T>
I think that is not a problem, I just have to supress it

How would I overload method in an interface?

if I have this interface
public interface someInterface {
// method 1
public String getValue(String arg1);
// method 2
public String getValue(String arg1, String arg2);
}
I want to be able to pass in 1 or 2 string to the getValue method without having to override both in each implementing class.
public class SomeClass1 impelments someInterface
{
#Override
public String getValue(String arg1);
}
public class SomeClass2 implements someInterface
{
#Override
public String getValue(String arg1, String arg2);
}
this won't work because SomeClass1 needs to implement method 2 and SomeClass2 needs to implement method 1.
Am I stuck doing this?
public interface someInterface2 {
public String getValue(String... args);
}
public class SomeClass3 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 1) {
throw IllegalArgumentException();
}
// code
}
}
public class SomeClass4 implements someInterface2
{
#Override
public String getValue(String... args) {
if (args.length != 2) {
throw IllegalArgumentException();
}
// code
}
}
someInterface2 someClass3 = new SomeClass3();
someInterface2 someClass4 = new SomeClass4();
String test1 = someClass3.getValue("String 1");
String test2 = someClass4.getValue("String 1, "String 2");
Is there a better way of doing this?
An interface serves as a contract for the users of that interface: you specify what methods are available (in all implementations) and how they are called. If two implementations of an interface need a different method, then that method should not be part of the interface:
public interface Lookup {
}
public class MapLookup implements Lookup {
public String getValue(String key) {
//...
}
}
public class GuavaLookup implements Lookup {
public String getValue(String row, String column) {
// ...
}
}
In your program, you will know which implementation you use, so you can simply call the right function:
public class Program {
private Lookup lookup = new MapLookup();
public void printLookup(String key) {
// I hardcoded lookup to be of type MapLookup, so I can cast:
System.out.println(((MapLookup)lookup).getValue(key));
}
}
Alternative approach
If your class Program is more generic and uses dependency injections, you may not know which implementation you have. Then, I would make a new interface Key, which can be either type of key:
public interface Lookup {
// ...
public String getValue(Key key);
}
public interface Key {
}
public MapKey implements Key {
private String key;
// ...
}
public GuavaKey implements Key {
private String row, column;
// ...
}
The dependency injection in your program might come from some factory implementation. Since you cannot know which type of lookup you use, you need a single contract for getValue.
public interface Factory {
public Lookup getLookup();
public Key getKey();
}
public class Program {
private Lookup lookup;
public Program(Factory factory) {
lookup = factory.getLookup();
}
public void printLookup(Factory factory) {
System.out.println((lookup.getValue(factory.getKey()));
}
}
As of Java 8, you can have an interface provide an implementation of a method, through the use of the default keyword. Therefore a new solution would be to provide a default implementation of both methods which maybe throws an exception, then derive the actual implementation from the default interface.
Anyways here is how you can do this:
public interface SomeInterface {
// method 1
default String getValue(String arg1) {
// you decide what happens with this default implementation
}
// method 2
default String getValue(String arg1, String arg2) {
// you decide what happens with this default implementation
}
}
Finally, make the classes override the correct methods
public class SomeClass1 implements SomeInterface {
#Override
public String getValue(String arg1) {
return arg1;
}
}
public class SomeClass2 implements SomeInterface {
#Override
public String getValue(String arg1, String arg2) {
return arg1 + " " + arg2;
}
}
A solution (not very elegant) might look loke this:
public abstract class SomeClass {
public String getValue(String arg1) {
throw new IllegalArgumentException();
}
public String getValue(String arg1, String arg2) {
throw new IllegalArgumentException();
}
}
public class SomeClass1 extends SomeClass {
public String getValue(String arg1) {
// return sth
}
}
public class SomeClass2 extends SomeClass {
public String getValue(String arg1, String arg2) {
// return sth
}
}
However there's a drawback - SomeClass1 and SomeClass2 can't inherit directly other class.
If the second value can be considered optional in a sense and you always have the 2 arguments when calling you could create a wrapper class which implements the 2 parameter interface passing the 1 parameter implementation as a constructor parameter and calling that in the method, e.g. something like this:
interface A{
method1(P1)
}
interface B{
method2(P1, P2)
}
class Wrap implements B{
Wrap(A impl)
override method2(P1, P2){
call impl.method1(P1)
}
}
public interface SomeInterface {
default void print(String s) {
System.out.println(s);
}
}
public class SomeClass implements SomeInterface {
/**
* Note the this overloads {#link SomeInterface#print(String)},
* not overrides it!
*/
public void print(int i) {
System.out.println(i);
}
}

Categories

Resources