Refactor multiple overloaded methods using generics - java

I have a class that contains several overloaded methods, such as:
interface SharedInterface
{
public void commonMethod();
}
class Model1 implements SharedInterface
{
public void commonMethod(){}
public int foo(){ return 1; }
}
class Model2 implements SharedInterface
{
public void commonMethod(){}
public String bar(){ return "2"; }
}
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( Model1 model )
{
external.calculate( model.foo() );
}
public void handle( Model2 model )
{
external.calculate( model.bar() );
}
}
I want to make the Client class more generic so that it can handle any type of Model in the future. However, because each Model has its own specific public methods, the Client.handle() method needs to change its behaviour according to the given Model. For example, if a Model1 instance is given, then call the method foo() of that model; if a Model2 instance is given, then call the method bar(), etc. In the future more types of models will be created. The following solution breaks the open closed principle and seems like a very bad practice:
class Client
{
private ExternalClass external = new ExternalClass();
public void handle( SharedInterface model )
{
if( model instanceof Model1 )
external.calculate( model.foo() );
else if( model instanceof Model2 )
external.calculate( model.bar() );
}
}
I am thinking of using Generics but I am not sure how generics could solve this.
Please note that the Client class has dependencies (makes use of libraries). The Models have to be POJOs without any dependencies to any other class. Therefore, because of the fact that the implementation of Client.handle() makes use of these dependencies, the method cannot be moved inside the Model classes.
Could someone please provide some alternatives?

Visitor design pattern best suits your problem... Link can help you out
https://sourcemaking.com/design_patterns/visitor..

Your handling logic is different for each type and the different behavior has to be described somewhere, for each Model you add, you have to have a piece of handling logic, this is a perfect case for overloading -- which you already do in your first code bit.
If you're dead set on keeping Client clear of those implementations. You can define the different handling logic in wrappers (adapters) for your data POJOs and pass those to handle(), e.g.:
class Client {
private ExternalClass external = new ExternalClass();
public void handle(PojoAdapter<?> model) {
model.getExecuted(external);
}
}
// Actually, generics are not necessary here, just to
// avoid declaring the same model field with different type
// in each implementation
abstract class PojoAdapter<T extends SharedInterface> {
protected T model;
public PojoAdapter(T model) {
this.model = model;
}
public abstract void getExecuted(ExternalClass excls);
}
class Model1Adapter extends PojoAdapter<Model1> {
#Override public void getExecuted(ExternalClass excls) {
external.calculate(model.foo());
}
}
class Model2Adapter extends PojoAdapter<Model2>{
#Override public void getExecuted(ExternalClass excls) {
external.calculate(model.bar());
}
}

Related

How to create a new object based on interface implementation

Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.

Default/Mixin Generic In java

I am wondering if i can replace the generic type upon class initialization ( without inheritance ).
The case is as below .
I have bunch of generic actor + builder class in my module and distribute this to people who wants to use it in my team while keeping the actor and the entry point of fluent interface generic.
The requirement is how can people supply their own builder ( not extending ) to do the stuff they want.
Current state:
class MessageBuilder {
public MessageBuilder msg(String msg) {
//do something
}
}
class Actor {
public MessageBuilder newMessage() {
return new MessageBuilder();
}
}
class Main {
#Test
public void testActor() {
Actor actor = new Actor();
actor.newMessage().msg("sss").send();
}
}
Desired state:
class MessageBuilder{
public MessageBuilder msg(String msg) {
//do something
}
//more fluent api...
}
// project specific - dont want to extend from generic one as this should be contains its own fluent interface
class MyCustomMessageBuilder {
public MyCustomMessageBuilder rawstr(String rawstr) {
//do something
}
}
class Actor<T> {
public T newMessage() {
return (T)builderFactory.getInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor(BuilderFactory);
actor.newMessage().rawstr("sss").send();
}
}
It's not possible without some known tricks.
First, Java implements Generics with type erasure (more information on type erasure), therefore the compiler will:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
In practice, this means that Actor<Builder1> and Actor<Builder2> are the exact same class after it gets compiled. In both cases, newMessage is implemented as follows:
class Actor {
public Object newMessage() {
...
}
}
It's not possible for newMessage to have different implementations based on the type parameter and it's not possible for newMessage to ask for the type of T because it gets removed.
Having said that, you can pass in type information:
class Actor<T> {
private Class<T> klass;
public Actor(Class<T> klass) {
this.klass = klass;
}
public T newMessage() {
return klass.newInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor<>(MyCustomMessageBuilder.class);
actor.newMessage().rawstr("sss").send();
}
}
I'd go with a factory approach. The builder should be supplied by a factory:
class Actor<MsgBuilder> {
private final Supplier<MsgBuilder> messageBuilderFactory;
public Actor(Supplier<MsgBuilder> builderFactory) {
this.messageBuilderFactory = builderFactory;
}
public MsgBuilder newMessage() {
return messageBuilderFactory.get();
}
}
This way offers flexibility in creating the message builder without sacrificing type safety and also no need for ugly casting.

Java interface : Calling an implementation class based on object types

I have an interface and its 2 implementations say :
public interface ObjectProcessor {
public void process(List<String> objectNames);
}
public CarImpl implements ObjectProcessor {
#override
public void process(List<String> carNames){
//car logic
} }
public VanImpl implements ObjectProcessor {
#override
public void process(List<String> vanNames){
//van logic
}
}
Now the caller who uses this interface looks like :
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = null ;
if (VehicleType == VehicleType.CAR) {
processor = new CarImpl();
processor.process(vehicleNames);
}
}
VehicleType being an ENUM
This works fine. But is there anyway I can call an interface dynamically without
adding if statements. In the future if I am supporting another vehicle , I need to add an if statement along with a new implementation for the interface . How can I avoid this?
Overwrite abstract factory method in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new CarImpl();
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new VanImpl();
}
};
public abstract ObjectProcessor createImpl();
}
public void caller(VehicleType vehicleType, List<String> vehicleNames ) {
ObjectProcessor processor = vehicleType.createImpl();
processor.process(vehicleNames);
}
VechicleType combines enumeration with factory.
Or you can wirte all logics in enum like this.
public enum VehicleType {
Car {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// car logic
}
};
}
},
Van {
#Override
public ObjectProcessor createImpl() {
return new ObjectProcessor() {
#Override
public void process(List<String> objectNames) {
// van logic
}
};
}
};
public abstract ObjectProcessor createImpl();
}
In this case you don't need implementation classes (CarImpl, VanImpl, ...) any more.
Use Factory pattern. Here are some benefit from using it: http://javarevisited.blogspot.com/2011/12/factory-design-pattern-java-example.html#ixzz3ueUdV947
1) Factory method design pattern decouples the calling class from the target class, which result in less coupled and highly cohesive code?
2) Factory pattern in Java enables the subclasses to provide extended version of an object, because creating an object inside factory is more flexible than creating an object directly in the client. Since client is working on interface level any time you can enhance the implementation and return from Factory.
3) Another benefit of using Factory design pattern in Java is that it encourages consistency in Code since every time object is created using Factory rather than using different constructor at different client side.
4) Code written using Factory design pattern in Java is also easy to debug and troubleshoot because you have a centralized method for object creation and every client is getting object from same place
What you're basically implementing is a Factory pattern like proposed in the other answers. But in the end you will have to write an 'if' or 'switch' statement to select to correct implementation (or strategy) for your enum value. But like you mentioned yourself you'd have to extend this selection pattern whenever you add or remove an enum value. You can circumvent this by using a map like so:
public class ProcessorSelector {
private final Map<VehicleType, ObjectProcessor> processors;
public ProcessorSelector(Map<VehicleType, ObjectProcessor> processors) {
this.processors = processors;
}
public void process(VehicleType type, List<String> input) {
processors.get(type).process(input);
}
}
You can than configure your ProcessorSelector by passing a map with all the processor implementations mapped to the correct enum value (notice I used guava's ImmutableMap to conveniently construct the hashmap:
new ProcessorSelector(ImmutableMap.of(
VehicleType.CAR, new CarImpl(),
VehicleType.VAN, new VanImpl());
You'll never have to change your ProcessorSelector again, only the construction/configuration of the class. In fact you could say we just implemented the strategy pattern here. These selector classes are very common and if you feel you are implementing them quite often you could even use a more generic implementation, I recently described this in a blogpost: https://hansnuttin.wordpress.com/2015/12/03/functionselector/

Stateless Template method implementation

Let's say I have a Strategy interface :
public interface Strategy {
void perform();
}
And a template method to implement it :
public abstract class AbstractStrategy implements Strategy {
#Override
public void perform() {
String firstInfo = doStuff();
String secondInfo = firstDelegationToImplementor(firstInfo);
String thirdInfo = processSecondInfo(secondInfo);
String fourthInfo = secondDelegationToImplementor(thirdInfo);
finalProcessing(fourthInfo);
}
private void finalProcessing(String fourthInfo) {
//TODO automatically generated method body, provide implementation.
}
protected abstract String secondDelegationToImplementor(String thirdInfo);
protected abstract String firstDelegationToImplementor(String firstInfo);
private String processSecondInfo(String secondInfo) {
return "thirdResult";
}
private String doStuff() {
return "firstResult";
}
}
And I have a concrete subclass of that :
public class ConcreteStrategy extends AbstractStrategy {
private String firstInfo;
#Override
protected String secondDelegationToImplementor(String thirdInfo) {
return someMoreProcessing(firstInfo, thirdInfo);
}
private String someMoreProcessing(String firstInfo, String thirdInfo) {
return null;
}
private String someProcessing(String firstInfo) {
return null;
}
#Override
protected String firstDelegationToImplementor(String firstInfo) {
this.firstInfo = firstInfo;
return someProcessing(firstInfo);
}
}
But due to the fact that it needs to remember some intermediate result in between the method calls it is not stateless. Stateless classes have several advantages, they are automatically thread safe for instance.
So the question is : how can I make ConcreteStrategy stateless, while taking advantage of the template method?
(edit) Clarification : the published methods of both the interface and the template method class cannot change.
(note, I have solved this question already and will answer it myself, but I'll give others a chance to solve it)
Ok here's the answer I have come up with when I faced this :
public class StatelessConcreteStrategy implements Strategy {
#Override
public void perform() {
new ConcreteStrategy().perform();
}
}
StatelessConcreteStrategy is stateless. It has all the benefits any other stateless class has, and by delegating the perform() to a new ConcreteStrategy instance, it gets to use the template method pattern, and is able to 'remember' any data it wants to in between method calls.
In fact you'll most likely want to inline ConcreteStrategy to an inner or even anonymous inner class.

Separating Service Logic from Data

I have been looking over a couple of classes I have in an android project, and I realized that I have been mixing logic with data. Having realized how bad this can be to the readability and the test-ability of my project, I decided to do some refactoring in order to abstract away all services logic to separate services modules. However, since I have been relying on Java's polymorphism, I got lost and need some guidance.
Suppose I have this "to-be-changed" layout for a super data class, and two sub-classes:
public class DataItem {
/* some variables */
public saveToDB(/* Some Arguments */) {
/* do some stuff */
}
public render() {
/* render the class */
}
}
public class ChildDataItemA extends DataItem {
#Override
public saveToDB(/* Some Arguments */) {
super.saveToDB();
/* more specific logic to ChildDataItemA */
}
#Override
public render() {
/* render logic for ChildDataItemA */
}
}
public class ChildDataItemB extends DataItem {
#Override
public saveToDB(/* Some Arguments */) {
super.saveToDB();
/* more specific logic to ChildDataItemB */
}
#Override
public render() {
/* render logic for ChildDataItemB */
}
}
Now, I thought about moving the saveToDB() and render() methods to a service class. However, sometimes I need to be able to call these method into instance of compiled type DataItem without knowing its runtime type. For instance, I might want to make the following call:
List<DataItem> dataList;
for (DataItem item: dataList) {
item.saveToDB();
item.render();
}
Additionally, I thought of doing the following:
public class ChildDataItemB extends DataItem {
#Override
public saveToDB(/* Some Arguments */) {
super.saveToDB();
/* more specific logic to ChildDataItemB */
Service.saveToDBB();
}
#Override
public render() {
/* render logic for ChildDataItemB */
Service.renderB();
}
}
Where I still keep 'dummy' methods in each subclass that would call an appropriate service method. However, I do not think that this really achieves the separation I want since data classes will still know about services (bad!).
Any ideas on how to solve this?
Edit: Note that render() and saveToDB() are just generic examples of what these methods can be, so the problem is not really about choosing an ORM or SQL related techniques.
Visitor pattern to the rescue. Create a visitor interface and have each service implement this interface:
public interface DataItemVisitor {
// one method for each subtype you want to handle
void process(ChildDataItemA item);
void process(ChildDataItemB item);
}
public class PersistenceService implements DataItemVisitor { ... }
public class RenderService implements DataItemVisitor { ... }
Then have each DataItem implement an accept method:
public abstract class DataItem {
public abstract void accept(DataItemVisitor visitor);
}
public class ChildDataItemA extends DataItem {
#Override
public void accept(DataItemVisitor visitor) {
visitor.process(this);
}
}
public class ChildDataItemB extends DataItem {
#Override
public void accept(DataItemVisitor visitor) {
visitor.process(this);
}
}
Note that all accept implementations look the same but this refers to the correct type in each subclass. Now you can add new services without having to change the DataItem classes.
So you want to do:
List<DataItem> dataList;
for (DataItem item: dataList) {
service.saveToDB(item);
service.render(item);
}
For this you need to setup a system for your service to know more details from your DataItem subclass.
ORM's and serializers usually solve this via a metadata system, e.g. by finding an xml file with name matching the subclass, containing the properties to save or serialize.
ChildDataItemA.xml
<metaData>
<column name="..." property="..."/>
</metaData>
You could get the same result via reflection and annotations.
In your case, an application of the Bridge pattern could also work:
class DataItem {
public describeTo(MetaData metaData){
...
}
}
class Service {
public void saveToDB(DataItem item) {
MetaData metaData = new MetaData();
item.describeTo(metaData);
...
}
}
Your metadata could be decoupled from saving or rendering, so you can the same for both.
I would clean the "data" classes of render and saveToDB methods.
Instead, I would create a hierarchy of wrappers for DataItem (it does not have to mimic exactly the DataItem hierarchy). These wrappers will be the ones implementing those methods.
Additionally, I suggest that (if you can), you move to some ORM (Object-Relational Mapping) like Hibernate or JPA to get rid of the saveToDB method.
First of all the DataItem class should be clean, only with getters and setter and no logic at all, just like a POJO. moreover- your DataItem maybe should be abstract.
Now- for the logic, like others suggested I would use some ORM framework for the saveToDB part, but you said that it's not helping you cause it's android project and you have other methods like this as well.
So what I would do is to create an interface- IDataItemDAO, with the following logic:
public interface IDataItemDAO<T extends DataItem > {
public void saveToDB(T data, /* Some Arguments */);
... other methods that you need ...
}
I would create an abstract DAO for the DataItem and put it all the similar code of all DataItems:
public abstract class ChildDataItemADAO impelemets IDataItemDAO<DataItem> {
#Override
public void saveToDB(DataItem data, /* Some Arguments */); {
...
}
}
than I would create a DAO for each DataItem class that you have:
public class ChildDataItemADAO extends DataItemDAO impelemets IDataItemDAO<ChildDataItemA> {
#Override
public void saveToDB(ChildDataItemA data, /* Some Arguments */); {
super(data, ...);
//other specific saving
}
}
the other part is how to use the correct DAO for the correct instance, for this I would create a class that will bring me the correct DAO for the given instance, it is a very simple method if an if-else statements (or you can do it dynamically with a map of class and the DAO)
public DataItemDAO getDao(DataItem item) {
if (item instanceof ChildDataItemA) {
//save the instance ofcourse
return new ChildDataItemADAO();
}
}
so you should use it like this:
List<DataItem> dataList;
for (DataItem item: dataList) {
factory.getDao(item).saveToDB(item);
}
If you want separate logic from data you may try the following approach
Create your data class DataItem,ChildDataItemA, ChildDataItemB without the method operating on the data
Create an interface for some operations on you data class something like
public interface OperationGroup1OnDataItem {
public void saveToDB(DataItem dataItem/*plus other params*/) {
}
public void render(DataItem dataItem/*plus other params*/) {
}
......
}
Create a factory for implementing an OperationGroup provider
public class OperationFactoryProvider {
public static OperationGroup1OnDataItem getOperationGroup1For(Class class) {
....
}
}
Use it in you code:
List<DataItem> dataList;
for (DataItem item: dataList) {
OperationGroup1OnDataItem provider OperationFactoryProvider.getOperationGroup1For(item.class);
provider.saveToDB(item);
provider.render(item);
}
You can choose to implement the factory with a simple static map where you put the class (or the class fullName) as the key and an Object implementing the interface as the value; something like
Map<String,OperationGroup1OnDataItem> factoryMap= new HashMap<String,OperationGroup1OnDataItem>();
factoryMap.put(DataItem.class.getName(),new SomeClassThatImplementsOperationGroup1OnDataItemForDataItem());
factoryMap.put(ChildDataItemA.class.getName(),new SomeClassThatImplementsOperationGroup1OnDataItemForChildDataItemA());
The implementation of the getOperationGroup1For is:
return factoryMap.get(item.getClass().getName());
This is one example of separating logic from data, if you want separate logic from data your logic methods must be extracted from your data class; otherwise there is no separation. So I think every solution must start from removing logic methods.

Categories

Resources