Suppose i have an interface
public interface Action<T> {
void doWork(T t);
//can have multiple methods
}
Now this class is implemented by
public class DefaultAction implements Action<String> {
#Override
public void doWork(String s) {
System.out.println(s);
}
}
Now i have a flow which accepts action
public abstract class Flow<T> {
void execute(T t){
Action<T> action = getAction();
action.doWork(t);
}
abstract Action<T> getAction();
}
so i have flow that accepts double
public class AnotherActionFlow extends Flow<Double> {
#Override
Action<Double> getAction() {
return new AnotherActionSet();
}
}
which in turn uses the default action
public class AnotherActionSet implements Action<Double> {
DefaultAction defaultAction;
#Override
public void doWork(Double aDouble) {
defaultAction.doWork(String.valueOf(aDouble));
}
}
So in this case i have to always update the AnotherActionSet method whenever the action interface changes
Is their any workaround so that i can have the common logic to convert the double to string and then use the DefaultAction
Can any pattern help to convert the AnotherActionSet to DefaultAction in which i only specify String.valueOf(aDouble) so the values can be passed to DefaultAction
instead of writing same thing for every method
Summary
I want to reuse use the logic inside the DefaultAction for other actions which are a wrapper around the DefaultAction
For eg;
public class AnotherActionSet2 implements Action<Long> {
DefaultAction defaultAction;
#Override
public void doWork(Long long) {
defaultAction.doWork(String.valueOf(long));
}
}
public class AnotherActionSet3 implements Action<Integer> {
DefaultAction defaultAction;
#Override
public void doWork(Integer int) {
defaultAction.doWork(String.valueOf(int));
}
}
As you can see i have to write the mapping each time manually, instead is it possible to just pass the function which converts the give class to string and then i can use DefaultAction
So i just define Function<Double,String> dToS and plug it to DefaultAction and don't need to define the method again
You can use Java 8 lambda to get something that is much easier and more expressive.
Basically your Action is the same as standard Consumer from JDK, only that the name of the method change.
Then defaultAction look like that:
Consumer<String> defaultAction = s -> {System.out.println(s);}
And so AnotherActionSet can be expressed like that:
Consumer<Double> anotherActionSet = s -> {defaultAction.accept(String.valueOf(aDouble));}
You also discover that flow and action are doing exactly the same (taking a T and returning nothing) so one of the notion is redundant. And you could write:
Consumer<Double> anotherActionFlow = anotherActionSet;
Related
I have an enum from a common Library (it cannot be changed) as a field from a Class.
I need to use that enum values as a switch-case in order to do something accordingly (for example save some data to a database).
This is for a Java 11 micro-service using Spring as a framework.
What I did before knowing the enum has to stay immutable, I avoided an ugly switch case with an overridden abstract function inside the enum like this:
public enum InvoiceStatus {
DRAFT {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.draft(inputMessage);
}
},
VALID {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.valid(eiInvoiceFileMessage);
}
},
NOT_VALID {
#Override public void action(InputMessage inputMessage) {
invoiceFileService.notValid(eiInvoiceFileMessage);
}
};
//+20 more values...
#Autowired
InvoiceFileService invoiceFileService;
public abstract void action(InputMessage inputMessage);
}
and I simply called the enum like this, so with different values from the enum the called function from the service would be different without writing a long switch-case.
invoice.getStatus().action(inputMessage);
Now the new requirement needs the enum to live inside a common library so it can refer to InvoiceFileService class which will be only local to my project.
I tried different options like HashMaps but the code went ugly and un-maintainable.
Is there a clean way to extend the simple enum (with only values definition) and add to it the abstract function to do stuff? maybe java 8 added some new way to do this.
You could create a wrapper enum.
public enum WrappedInvoiceStatus {
DRAFT(InvoiceStatus.DRAFT, this::someAction),
// other values
private WrappedInvoiceStatus(InvoiceStatus status, Action action) {
this.status = status;
this.action = action;
}
private interface Action { // can be one of Java default functional interfaces as well
void doSomething(InputMessage msg);
}
private void someAction(InputMessage msg) {
// behavior
}
// some plumbing required
}
Basically I’m suggesting using wrapping and lambda expressions or method references. The world of functional programming takes some getting used to. Not everyone is a fan. Your mileage may vary.
As others already said, you can not extend the enum at runtime.
But an enum can implement an interface.
So the basic idea is:
You make an interface with the action as sole abstract method:
public interface InvoiceAction {
void action(InputMessage message);
}
Your enum implements that interface
public enum InvoiceStatus implements InvoiceAction {
// ... no other changes needed
}
In all the cases where you only need to use the actual action, change InvoiceStatus to InvoiceAction. This is the most risky change. Make sure to recompile all code.
Because InvoiceAction only has one abstract method, it's a functional interface, and can be implemented with a lambda expression:
invoice.setStatus(msg -> ...);
This change is probably the most invasive change, but it might be the right thing to do - if you need a different action next time, you won't have the same problem as today.
Enum type is not extendable and implicitly final as specified in JLS:-
An enum declaration is implicitly final unless it contains at least one enum constant that has a class body (§8.9.1).
Hence a class could not extends an enum type. However you could use wrapper or adapter pattern to add additional behaviours/fields of the enum. For example:-
#Service
public class SimpleInvoiceFileService implements InvoiceFileService{
private final InvoiceStatus invoiceStatus;
public SimpleInvoiceFileService(InvoiceStatus status){
invoiceStatus = status;
}
#Override
public void draft(InputMessage input){
this.invoiceStatus.action(input);
}
#Override
public void valid(InputMessage input){
this.invoiceStatus.action(input);
}
// Add more methods to InvoiceFileService interface
// as required and override them here.
}
JLS Reference:-
https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9
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/
Question
If one defines a public class Something <T> { ... }, then Java will complain about using a raw type if you do this: Something noparam = new Something();
Is it possible to define an interface or class that can be used with or without a type parameter?
Context
The frontend of a Java app interfaces asynchronously with our backend using callbacks:
public interface ResultCallback <T> {
public void onResult(T result);
public void onError();
}
Here's an example of the backend I'm talking about, with some basic CRUD operations using the callback above:
public interface Backend {
// create a new Comment for a specified blog Post
public void createComment(Post post, ResultCallback<Comment> callback);
// retrieve the Comment with the specified UUID
public void getComment(UUID id, ResultCallback<Comment> callback);
// delete the Comment with the specified UUID
public void deleteComment(UUID id, ResultCallback callback);
}
Notice that the delete operation's callback.onResult(T result) will not have a Comment parameter. It might make sense to parametrize that result with a Comment and just "return" the deleted Comment, even if it's just to satisfy the type parameter constraint of ResultCallback. I don't like this idea because the Comment is gone from the backend and no changes to it will persist.
Just for a usage example, the idea is that ResultCallbacks are defined in the frontend of the app and passed to the async backend. For example, to display a comment:
public CommentRenderer implements ResultCallback<Comment> {
#Override
public void onResult(Comment comment) {
// display the comment, commenter, date, etc. on screen
}
#Override
public void onError(String message) {
// display an error message
}
}
No, the closest thing to that comes to mind would be to use ResultCallback<Void> but that would still require you to give the onResult a null-argument which is kind of ugly.
In this case I would recommend you to either use a separate interface for the delete case or let ResultCallback have more than one method:
interface ResultCallback<T> {
void onResult(T t);
void onDelete(); // Called after delete.
void onError(String message);
}
If you think it is frustrating to override the onDelete even though you're rarely interested in "listening" for these type of events, you could give it an empty default implementation:
...
default void onDelete() {
// do nothing by default
}
...
An alternative for pre-Java 8, is to use an Adapter which would look like follows:
abstract class ResultAdapter<T> implements ResultCallback<T> {
#Override
public void onResult(T t) {
}
#Override
public void onDelete() {
}
#Override
public void onError(String msg) {
}
}
You can always use ResultCallback<Void> and use null in that case.
How a bout extended Generic Type?
public class Foo<T extends Comment> { ... }
public class FooDefault extends Foo< Baz > { ... }
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.
I have written custom dispathing/handling event system that generally look like this:
Event handler interface:
public interface EventHandler{
}
Base event class:
public abstract class Event<H extends EventHandler> {
public static Class Type<H> { }
public abstract void dispatch(H handler);
}
Handler manager:
public class HandlerManager {
private Map<Event.Type, List<EventHandler>> map = new HashMap<Event.Type, List<EventHandler>>();
public void register(Event.Type<H> type, H handler) {
if(map.get(type) == null) { map.put(type, new ArrayList<EventHandler>()); }
map.get(type).add(handler);
}
public void fire(Event<H> event) {...}
...
}
And everything is working fine but i want to use events like
public class DataChangeEvent<D> extends Event<DataChangeHandler<D>> {
public static final Type<?> TYPE = new Type<?>();
D data;
...
public void dispatch(DataChangeHandler<D> handler) {
handler.onDataChanged(this);
}
public D getData() { return data; }
}
public class DataChangeHandler<D> extends EventHandler {
void onDataChanged(DataChangeEvent<D> event);
}
and now when I register handler DataChangeHandler with manager that generates events for Strings and for example for Integers, this registered handler will receive both events what causes ClassCastException to occure when I want to read data.
I understand that generic dont have some special class and that despite of type defined in DataChangeHandler they are stored in the same list in handlers map.
Is there any way to make it work?
This seems like a really, really smelly design. Why should an event be typed with the class that handles that type of event? That's backwards. An EventHandler should be typed with the type of Events it handles.
So I didn't quite follow what you're actually trying to do but I think you're basically trying to do this:
private Map<Class<?>, List<EventHandler>> map;
public <T> void register(Class<? extends T> typeFilter, EventHandler<T> handler) {
map.get(typeFilter).add(handler);
}
//...later
//safe since we used a generic method to add
#SuppressWarnings("unchecked");
public void fire(Event<?> event) {
for ( EventHandler handler : map.get(event.getClass()) ) {
handler.onDataChanged(event);
}
}
//or similarly:
#SuppressWarnings("unchecked");
public void fire(Event<?> event) {
for ( Class<?> type : map.keySet() ) {
if ( !type.instanceOf(event) ) continue;
for ( EventHandler handler : map.get(type) ) {
handler.onDataChanged(event);
}
}
}
This type of design will filter out events that the handler can't handle.
Generics are largely a compile time feature. If you need the type at runtime you need to pass the class as an arguement and store it in a field.
IMHO: A more elegent way of creating a dispacter is to use an annotation. Like
#EventHandler
public void onMyEvent(MyEvent event) {
// is called when MyEvent is dispacted.
}