I have the following code
public abstract class Event {
public void fire(Object... args) {
// tell the event handler that if there are free resources it should call
// doEventStuff(args)
}
// this is not correct, but I basically want to be able to define a generic
// return type and be able to pass generic arguments. (T... args) would also
// be ok
public abstract <T, V> V doEventStuff(T args);
}
public class A extends Event {
// This is what I want to do
#Overide
public String doEventStuff(String str) {
if(str == "foo") {
return "bar";
} else {
return "fail";
}
}
}
somewhere() {
EventHandler eh = new EventHandler();
Event a = new A();
eh.add(a);
System.out.println(a.fire("foo")); //output is bar
}
However I don't know how to do this, as I cannot override doEventStuff with something specific.
Does anyone know how to do this?
It's not really clear what you're trying to do, but perhaps you just need to make Event itself generic:
public abstract class Event<T, V>
{
public abstract V doEventStuff(T args);
}
public class A extends Event<String, String>
{
#Override public String doEventStuff(String str)
{
...
}
}
You're using generics but you are not providing a binding.
public abstract class Event<I, O> { // <-- I is input O is Output
public abstract O doEventStuff(I args);
}
public class A extends Event<String, String> { // <-- binding in the impl.
#Override
public String doEventStuff(String str) {
}
}
Or simpler with only one generic binding...
public abstract class Event<T> { // <-- only one provided
public abstract T doEventStuff(T args);
}
public class A extends Event<String> { // <-- binding the impl.
#Override
public String doEventStuff(String str) {
}
}
Related
I have multiple services that implement interface with one method - execute(). Each service uses this method to execute some actions based on a String value, which, in original code, is enum, so those values are constants.
interface Service{
public void execute();
}
class Service1 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething(payload);
}
}
}
class Service2 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething1(payload);
}
if(payloadType.equals("type2")){
doSomething2(payload);
}
}
}
I want to avoid writing same if statements each time I create a new Service. Problem is, that each Service doesn't have to execute actions based on each string types. So Service1 executes action when type is equal to "type1", however Service2 executes actions based on "type1" and "type2".
I tried following solution:
class Main {
public static void main(String[] args) {
exec(new B(), "type2");
}
private static void exec(Service service, JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
Init i = (Init)service;
i.init(payload);
}
if(payloadType.equals("type2")){
Action a = (Action)service;
a.action(payload);
}
}
}
interface Service{
}
interface Init{
public void init(JSONObject payload);
}
interface Action{
public void action(JSONObject payload);
}
class A implements Service, Init{
#Override
public void init(JSONObject payload){
doSomething(payload);
}
}
class B implements Service, Init, Action{
#Override
public void init(JSONObject payload){
doSomething1(payload);
}
#Override
public void action(JSONObject payload){
doSomething2(payload);
}
}
The above code works, but I don't like using casting. I think it's not a good practice, also very unsafe. Could you suggest, what design pattern or other solution could I use here? I tried visitor, but I couldn't figure out the right implementation with this case.
UPDATE
Thanks for all the answers, they were very helpfull. I managed to achieve what I was looking for. Here's the code that finally works.
public class Main {
public static B b = new B();
public static A a = new A();
public static void main(String[] args) {
exec(b, "init");
}
private static void exec(Service service, String type){
if(type.equals("init") && service instanceof Init){
service.fillCarrier(new InitCarrier());
}
if(type.equals("action") && service instanceof Action){
service.fillCarrier(new ActionCarrier());
}
}
}
interface Carrier<T>{
public void set(T t);
}
class InitCarrier implements Carrier<Init>{
public void set(Init init){
init.init();
}
}
class ActionCarrier implements Carrier<Action>{
public void set(Action action){
action.action();
}
}
abstract class Service{
public void fillCarrier(Carrier carrier){
carrier.set(this);
}
}
interface Init{
public void init();
}
interface Action {
public void action();
}
class A extends Service implements Init{
#Override
public void init(){
System.out.println("init a");
}
}
class B extends Service implements Init, Action{
#Override
public void init() {
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
}
To achieve this requirement, we need to pattern.
Factory pattern.
Strategy pattern.
TypeFactory creates an object based on the string we delivered. Each Type implementation implements a doSomething() method in its own way. (factory pattern is used here)
Type Strategy:
interface Type{
public void doSomething();
}
class TypeOne implements Type{
#Override
public void doSomething() {
System.out.println("Type One!");
}
}
class TypeTwo implements Type{
#Override
public void doSomething() {
System.out.println("Type Two!");
}
}
Type Factory:
class TypeFactory{
Type type;
public Type createType(String condition) {
if (condition == null || condition.isEmpty()) {
return null;
}
if ("type1".equals(condition)) {
return new TypeOne();
}
else if ("type2".equals(condition)) {
return new TypeTwo();
}
return null;
}
}
Now to achieve the final goal, we need to declare a Service interface with an execute method. This execute method takes Type as an input parameter. Based on which type you actually pass, the corresponding doSometing method will be invoked. (strategy pattern used only)
interface Service{
public void execute(Type type);
}
class ServiceOne implements Service{
#Override
public void execute(Type type) {
System.out.print("Service One - ");
type.doSomething();
}
}
class ServiceTwo implements Service{
#Override
public void execute(Type type) {
System.out.print("Service Two - ");
type.doSomething();
}
}
Main Class looks like this:
public class DesignPatternCombo {
public static void main(String[] args) {
Type typeOne = new TypeFactory().createType("type1");
Type typeTwo = new TypeFactory().createType("type2");
Service serviceOne = new ServiceOne();
serviceOne.execute(typeOne);
Service serviceTwo = new ServiceTwo();
serviceTwo.execute(typeOne);
serviceTwo.execute(typeTwo);
}
}
Expected output:
Service One - Type One!
Service Two - Type One!
Service Two - Type Two!
Tricky question, I may have a solution that could work.
That would be to store the Types, with the code that type does in the form of a HashMap.
HashMap<String, Function<Void, Void>> types = new HashMap<String, Function<Void, Void>>();
Then in the main function, you would fill up the HashMap with the names of the types, and the function it runs.
types.put("Type1",()->{
/*Do something*/
});
types.put("Type2",()->{
/*Do something*/
});
types.put("Type3",()->{
/*Do something*/
});
Then in the Service, you would have an array of Strings for what types it uses. Such as:
String[] serviceTypes = {"Type1", "Type2"};
Finally, in the execute function of the Service you would run the corresponding lambda to the string.
public void execute(String type){
if((new ArrayList<>(Arrays.asList(serviceTypes))).contains(type)) {
Main.types.get(type);
}
}
You might work with an abstract base class.
The base class implements Service and has the execute() method. It does not get around if statements, but after all it could have a list of allowed values, and as soon as the type parameter is contained in the list it would call another method. Per default the method does nothing.
Concise subclasses of the base no longer need to perform the if conditions as they simply override the single methods in the base class. So this works for a whole bunch of quite similar services.
The advantage of this approach is if you have some exotic, incompatible type of service you can skip the if statements by directly overwriting the execute() method. So that pattern is extensible, which is probably worth more than saving a few more if statements.
You can solve this elegantly with the Strategy Design Pattern.
Create a common interface called Strategy
interface Strategy {
void execute(JSONObject payload);
}
Create multiple implementations of Strategy according to your needs:
class ServiceType1 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type1"
}
}
class ServiceType2 implements Strategy {
//constructors and fields
#Override
public void execute(JSONObject payload) {
//code to be executed for "type2"
}
}
...
Group the Service implementations by type, eg.:
Map<String, Strategy> strategyMap = new HashMap<>();
strategyMap.put("type1", new ServiceType1());
strategyMap.put("type2", new ServiceType2());
...
Invoke the desired Service without the need for any if statements, like this:
private static void exec(String payloadType, JSONObject payload) {
strategyMap.get(payloadType).execute(payload);
}
P.S.: if all implementations of Strategy share some common behaviour, you can convert Strategy from interface to abstract class and move the common behaviour there.
wow, your architecture seems much complex. you should consider better hierarchy. but if you can't, why don't you just make a method on Service and let the subtype decide what behavior they want. Then you can call that method from Service to execute
static class Main {
public static void main(String[] args) {
exec(new B());
}
private static void exec(Service service){
service.execute();
}
}
interface Service{
void execute();
}
interface Init{
public void init();
}
interface Action{
public void action();
}
static class A implements Service, Init{
#Override
public void init(){
System.out.println("init a");
}
#Override
public void execute(){
init();
}
}
static class B implements Service, Init, Action{
#Override
public void init(){
System.out.println("init b");
}
#Override
public void action(){
System.out.println("action");
}
#Override
public void execute(){
action();
}
}
What about extracting common logic to the separate class. It cloud be:
BaseService and all other services should implement this one;
ServiceDelegate and all other services should delegate all work to this one.
The below snippet provides the first solution.
// This is you Service interface
public interface Service {
void execute(JSONObject payload, String payloadType);
}
// This is base implementation. Use `Map` to replace `if` statements
public abstract class BaseService implements Service {
private static final Consumer<JSONObject> NULL = jsonObject -> { };
private final Map<String, Consumer<JSONObject>> consumers;
protected BaseService(Map<String, Consumer<JSONObject>> consumers) {
this.consumers = consumers == null || consumers.isEmpty() ? Map.of()
: Collections.unmodifiableMap(consumers);
}
#Override
public final void execute(JSONObject payload, String payloadType) {
consumers.getOrDefault(payloadType, NULL).accept(payload);
}
}
public class ConcreteService extends BaseService {
private static final Consumer<JSONObject> DO_SOMETHING_TYPE1 = jsonObject -> {
// TODO implementation for "type1"
};
private static final Consumer<JSONObject> DO_SOMETHING_TYPE2 = jsonObject -> {
// TODO implementation for "type2"
};
public ConcreteService() {
super(Map.of(
"type1", DO_SOMETHING_TYPE1,
"type2", DO_SOMETHING_TYPE2));
}
}
I have few classes that implements some interface. Now I want to create new class, which can extend one of them, based on runtime calculation while using interfaces methods. Let's talk in code:
public interface Interface {
public void doSomething();
}
public class A implements Interface {
#Override
public void doSomething() {
System.out.println("hello");
}
}
public class B implements Interface {
#Override
public void doSomething() {
System.out.println("hi");
}
}
These are existing classes, so now I need to do something like this (which is not working of course):
public class C<T extends Interface> extends T {
public void doSomethingElse() {
this.doSomething();
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C<A>();
} else {
c = new C<B>();
}
c.doSomethingElse();
}
}
Is it possible somehow, except the way that I pass argument Interface other to C's constructor and store to class property..?
A class cannot extend from its type parameter.
Use composition instead of inheritance:
public class C<T extends Interface> {
private final T foo;
public C(T foo){
this.foo = foo;
}
public void doSomethingElse() {
foo.doSomething();
}
public static void main(String[] args) {
C<?> c;
if(isSomethingLoaded) {
c = new C<>(new A());
} else {
c = new C<>(new B());
}
c.doSomethingElse();
}
}
You might even not need the type parameter here, but just use the interface type as argument/ member type.
I think it's situations like this which show why we have the rule of favouring composition over inheritance. Consider this solution using composition:
public class Test {
public interface Interface {
void doSomething();
}
public static class A implements Interface {
#Override
public void doSomething() {
System.out.println("Doing A");
}
}
public static class B implements Interface {
#Override
public void doSomething() {
System.out.println("Doing B");
}
}
public static class C implements Interface {
private Interface composedWith;
public C(Interface i) {
this.composedWith = i;
}
#Override
public void doSomething() {
this.composedWith.doSomething();
}
}
public static void main(String[] args) {
C c;
if(isSomethingLoaded) {
c = new C(new A());
} else {
c = new C(new B());
}
c.doSomething();
}
}
Personally, I feel this is a clearer and move flexible way of achieving what you are trying to do.
I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.
I have some code as follows (excerpt):
public interface Event<S> {
S getSource();
}
public interface Subscriber<E> {
void update(E event);
}
public interface EventPublisher<S, E extends Event<S>> {
void addSubscription(S source, Subscriber<E> subscriber);
void removeSubscription(S source, Subscriber<E> subscriber);
}
public class SubscriptionManager<S, E extends Event<S>> implements Subscriber<E>, EventPublisher<S, E> {
...
}
public class MyEvent implements Event<MyEventSource> {
...
}
This all works fine, however, my problem is when I try something like this:
public class MyEventHandler {
private final SubscriptionManager<Class<? extends Event<?>>, ? extends Event<?>> subscriptionManager = new SubscriptionManager<>();
Subscriber<? extends Event<?>> subscriber = ...;
subscriptionManager.addSubscription(MyEvent.class, subscriber); **// Compile error**
}
I get the following error:
The method addSubscription(Class<? extends Event<?>>, Subscriber<capture#3-of ? extends Event<?>>) in the type SubscriptionManager<Class<? extends Event<?>>,capture#3-of ? extends Event<?>> is not applicable for the arguments (Class<MyEvent>, Subscriber<capture#5-of ? extends Event<?>>)
Can anyone tell me what's wrong?
Thanks
To be honest with you I think there's some design error in your code. It almost looks like a perfectly designed pattern, but something doesn't add up. You can probably omit half of generic parameters and make it more straightforward.
Please consider the code below. Entire framework is parametrized by a single parameter. Everything compiles and there are no raw types used.
Also, note that MyEvent is never used in the framework definition. It's a convenience class.
You can safely invoke subscriptionManager.update(new MyEvent()); somewhere in your code.
More complicated arrangements are possible too, but I believe that's the one you need.
Please let me know if that works for you.
static interface Event<S> {
S getSource();
}
static interface Subscriber<S> {
void update(Event<S> event);
}
static interface EventPublisher<S> {
void addSubscription(Class<S> sourceClass, Subscriber<S> subscriber);
void removeSubscription(Class<S> sourceClass, Subscriber<S> subscriber);
}
static class SubscriptionManager<S> implements Subscriber<S>, EventPublisher<S> {
public void addSubscription(Class<S> sourceClass, Subscriber<S> subscriber) {
}
public void removeSubscription(Class<S> sourceClass, Subscriber<S> subscriber) {
}
public void update(Event<S> event) {
}
}
static class MyEvent implements Event<String> {
public String getSource() {
return null;
}
}
static class MyEventHandler {
private final SubscriptionManager<String> subscriptionManager = new SubscriptionManager<String>();
public MyEventHandler() {
Subscriber<String> subscriber = null;
subscriptionManager.addSubscription(String.class, subscriber);
}
}
I'm developing an application which builds on a class written by another developer (for which I do not have the source).
I wish to use all of the functionality of said class but also to extend it with additional functionality. Ordinarily to achieve this I would have defined an interface (MyInterface) and have extended the external class (TheirClass) from my own (MyClass) while implementing MyInterface.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
The problem is complicated by the fact that:
I now wish to create a new class (MyNewClass) which adds additional functionality to MyClass but I don't want my code to be dependent on TheirClass.
I wish to be able to use my class as a parameter to the method of TheirOtherClass.
To combat this I refactored my code to instead use composition over inheritance and implementing TheirClassInterface. This works but requires me to implement many methods and delegate them to theirClassObject (in reality TheirClassInterface contains a very large number of methods).
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass implements TheirClassInterface, MyInterface {
private TheirClass theirClassObject;
public void myMethod1() { ... }
public void theirMethod1() { theirClassObject.theirMethod1(); }
public void theirMethod2() { theirClassObject.theirMethod2(); }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
My question is whether my approach is appropriate in this case and whether it could be improved upon as it seems to me that my code uses an excessive amount of delegation to get the job done.
Many thanks for any guidance anyone can give on this.
Danny
First, as java is a strongly-typed single inheritance language, you cannot escape the delegation.
But you can avoid having to write a lot of delegation CODE, by using a dirty little trick with Proxies and reflection.
Code follows
public interface Interface1 {
void m1();
}
public interface Interface2 {
void m2();
}
public class Class1 implements Interface1 {
public void m1() {
System.out.println(1);
}
}
public class Class2 implements Interface2 {
public void m2() {
System.out.println(2);
}
}
public interface MixinInterface extends Interface1, Interface2 {
}
And this is how the magic happens
package j.with.pseudo.multiple.inheritance;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MixinBuilder {
public static Object buildMixed(Class _interface, Object... impls){
InvocationHandler h = new MixinHandler(_interface.getInterfaces(), impls);
return Proxy.newProxyInstance(MixinBuilder.class.getClassLoader(),
new Class[]{_interface}, h);
}
public static void main(String[] args) {
Class1 o1 = new Class1();
Class2 o2 = new Class2();
MixinInterface almost_like_multiple_inheritance_guy =
(MixinInterface) buildMixed(MixinInterface.class, o1, o2);
almost_like_multiple_inheritance_guy.m1();
almost_like_multiple_inheritance_guy.m2();
}
private static class MixinHandler implements InvocationHandler{
private Class[] interfaces;
private Object[] impls;
public MixinHandler(Class[] interfaces, Object[] impls) {
this.interfaces = interfaces;
this.impls = impls;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
int i=0;
for(Class _interface : interfaces){
if(method.getDeclaringClass().isAssignableFrom(_interface)){
return method.invoke(impls[i], args);
}
i++;
}
// TODO Auto-generated method stub
throw new RuntimeException("Method not found: "+method);
}
}
}
Pretty cool huh? :-)
You can't not-depend on a class if you're extending it; it's like having a definition of Human, which does not depend on the definition of Mammal, your optinos are to rewrite everything in the parent, or depend on it.
Many thanks for the answers so far. I've come up with a solution which I think seems reasonable and allows me to fully encapsulate the foreign class.
At the moment I've returned to the method discussed in the first block of code (repeated and extended below) and am now implementing my MyInterface interface for MyNewClass and delegating all interface operations to a composed object. The object to delegate to is decided at runtime by calling a static method on a Factory.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass implements MyInterface {
private MyInterface myObject;
public MyNewClass() {
myObject = MyClassFactory.createMyClass();
}
public void myMethod1() {
myObject.myMethod();
}
public void MyNewClassMethod() { ... }
}
Once again, thanks for the ideas. I'm now going to look into them all and see if I can use them to improve my code.
Cheers,
Danny