I have a class called Router that takes care of interfacing with Retrofit. So in here are all the core methods. Then i have an abstract class called ConfigurableRouter (that extends Router), that allows me to configure my router. Now i want that i can create children of the ConfigurabelRouter (In fact it is an abstract class) with different defults values.
This is an example how it works:
Router.configure(M_Rout.class)
.setPath("close-pi")
.setParams(params)
.setRequestMethod(Router.RequestMethod.POST)
.setIsAuthRequested(true)
.setCallback(new RequestResponse() {
#Override
protected void onSuccess(HashMap<String, String> responseItems) {}
#Override
protected void onGeneralError(int responseCode) {}
#Override
public void onFailure() {}
})
.sendRequest(getActivity());
This is how the Router.configure() methods work:
public static ConfigurableRouter configure(Class<? extends ConfigurableRouter> aClass){
ConfigurableRouter configurableRouter = null;
try {
configurableRouter = aClass.newInstance();
//obj is a newly created object of the passed in type
} catch (Exception ignored) { }
return configurableRouter;
}
And this is an example of a ConfigurableRouter method:
public ConfigurableRouter setParams(HashMap<Stthring, Object> params){
super.setRouterParams(params);
return this;
}
And this is the M_Router class:
public class M_Rout extends ConfigurableRouter {
#Override
public String setBasepath() {
return "www.xxxxxxx.xx/";
}
#Override
public String setInDebigBasePath() {
return "www.debugxxxxxxx.xx/";
}
#Override
public boolean isDebugging() {
return false;
}
#Override
public RequestMethod setDefultRequestMethod() {
return RequestMethod.POST;
}
#Override
public RequestResponse setDefultResponse() {
return new RequestResponse() {
#Override
protected void onSuccess(HashMap<String, String> responseItems) {
Log.d("RouterLog", "PigSUCSESSSpig");
}
#Override
protected void onGeneralError(int responseCode) {
}
#Override
public void onFailure() {
}
};
}
#Override
public ConfigurableRouter setAuthToken(String authToken) {
return super.setAuthToken("tokenExample");
}
public void setIsAuthRequested(boolean b){
//
}
}
Now my problem is that i cannot acces the non-overriden methods in M_Router class, like setIsAuthRequested(), that is in the first snippet. I have no idea how i can do.. tried in different ways but nothing. How can i do?
public abstract class Person {
abstract void sayName();
}
which has two implementations:
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
}
and
public class RegularPerson extends Person {
void sayName() {
System.out.println("I will say my name");
}
void givesBusinessCard() {
// whatever
}
}
Now, if you create a method like this:
public void handlePerson(Person person) {
}
you will be able to call the sayName() method on it, because no matter what type of Person it is, it will always have an implementation of sayName()
Now, let's say you want to pass an instance of RegularPerson, and call the givesBusinessCard(), this won't immediately work.
Even if all you ever pass as parameters are of type RegularPerson, the JVM running the code doesn't (can't) know this
Someone else could create other subclasses, and change that line of thought.
As far as the JVM knows, it's just a Person, and all Person provides is the sayName() method.
Let's say you need to be able to call the givesBusinessCard() method, you have 3 options.
Alter the method you call. If you need givesBusinessCard() to be called, you know it's a RegularPerson, so you can say:
public void handlePerson(RegularPerson person) {
}
Alter your abstract class, add the method there, and provide either a failing or an empty implementation of the method in LoudPerson
public abstract class Person {
abstract void sayName();
abstract void givesBusinessCard();
}
and
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
void givesBusinessCard() throws UnsupportedOperationException {
throw new UnsupportedOperationException("not needed here");
}
}
or
public class LoudPerson extends Person {
void sayName() {
System.out.println("I yell my name!!");
}
void givesBusinessCard() {
}
}
Cast your person to RegularPerson before calling it, but make sure to do an instance check:
public void handlePerson(Person person) {
// ..
if ( person instanceof RegularPerson ) {
RegularPerson p = (RegularPerson)person;
p.givesBusinessCard();
}
// ..
}
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));
}
}
Ok, so recently I wanted to implement the following
public enum ObjectTypes {
STRING,
INTEGER
}
interface IObjectEnhancer{
void enhance(String s);
void enhance(Integer i);
ObjectTypes getLastEnhancedType();
}
class ObjectEnhancer implements IObjectEnhancer{
ObjectTypes lastUsedType=null;
#CallSuper
#Override
public void enhance(String s) {
this.lastUsedType=ObjectTypes.STRING;
}
#CallSuper
#Override
public void enhance(Integer i) {
this.lastUsedType=ObjectTypes.INTEGER;
}
#Override
final public ObjectTypes getLastEnhancedType() {
return lastUsedType;
}
}
class ObjectEnhancerChild extends ObjectEnhancer{
#Override
public void enhance(String s) {
super.enhance(s);
//child code
}
#Override
public void enhance(Integer i) {
super.enhance(i);
//child code
}
}
And for safety I wanted to add #CallSuper because I really want only the parent to remember the types but I also want the enhance(String) and enhance(Integer) to be abstract so that no clumsy future person (me included) forgets to actually implement these methods.
So below is a method to handle this sort of situation that apparently only I am having and the internet doesn't really have advice on, it might seem stupid to worry about such a small thing but if you have 10+ methods it stars becoming a nightmare(feedback and other solutions welcome):
Just make new abstract methods so that the child is forced to implement them and parent methods call the abstract methods instead of using #CallSuper:
abstract class ObjectEnhancer implements IObjectEnhancer{ //add abstract to parent
ObjectTypes lastUsedType=null;
abstract void enhance2(String s); //new
abstract void enhance2(Integer i); //new
//removed #CallSuper
#Override
final public void enhance(String s) { //changed to final
this.lastUsedType=ObjectTypes.String;
enhance2(s); //new
}
//removed #CallSuper
#Override
final public void enhance(Integer i) { //changed to final
this.lastUsedType=ObjectTypes.Integer;
enhance2(i); //new
}
#Override
final public ObjectTypes getLastEnhancedType() {
return lastUsedType;
}
}
class ObjectEnhancerChild extends ObjectEnhancer{
#Override
public void enhance2(String s) { //changed to abstract method
//removed super.enhance(s);
//code
}
#Override
public void enhance2(Integer i) { //changed to abstract method
//removed super.enhance(i);
//code
}
}
I'm having an issue with interfaces, i have a class that implements an interface which i expect to fire after a network response of 200. My interface is not called (how do i hook it to my NetworkrequestClass?)
//My class
public class MyClass extends AnotherClass implements MyDesiredListener{
private void myMethod(){
if (!value) {
NetworkCallClass.specificRequest(); //To call onDesiredLoadedData
}
}
#Override
onDesiredLoadedData(){
//Update Value
}
}
//My inteface in its own file
interface MyDesiredListener{
onDesiredLoadedData();
}
I'm not sure if I understand you correctly, but if I did here you are:
public class FirstClass implements MyInterface {
public void method() {
NetworkCallClass clazz = new NetworkCallClass(this);
clazz.specificRequest();
}
#Override
public void onDesiredLoadedData() {
// here you are your callback
}
}
public class NetworkCallClass {
MyInterface _callbacks;
public NetworkCallClass(MyInterface callbacks) {
_callbacks = callbacks;
}
public void specificRequest() {
// code
if (networkResponse == 200) {
_callbacks.onDesiredLoadedData();
}
}
}
Can Someone tell me with an example why an class should be defined inside an interface.
The below is the simple code i was trying.
interface Watsapp
{
class A
{
public void Validate()
{
}
};
abstract public void SendText();
public void SendPic();
};
its totally depends on logic requirements.
whenever we declare inner class, it treats as a data member so here also you can treat this class as a data member
just assume scenario some one needs object of A inside Interface and there is no class right now.
see eg.
public interface Watsapp
{
class A
{
public void Validate()
{
}
public String iDoSomething()
{
return "i did";
}
};
public A objOfA = new A();
abstract public void SendText();
public void SendPic();
};
And main Class is bellow:
public class TestMain {
public static void main(String[] str){
System.out.println( Watsapp.objOfA.iDoSomething());
}
}
mostly people create anonymous class for one time use, but here You created a class with name.
see:
public interface Watsapp
{
/*class A
{
public void Validate()
{
}
public String iDoSomething()
{
return "i did";
}
};*/
Thread t = new Thread()
{
public void run() {
// something ...
}
};
abstract public void SendText();
public void SendPic();
};
Thank you.
I'm using the Observable class / Observer interface in Java to implement the observer pattern. The Observer interface requires overwriting the update(Observable o, Object arg) method.
The problem is that I'm observing a fair number of classes, and my update() method has gotten very large:
public class Foo implements Observer {
....
public void update(Observable o, Object param) {
if (o instanceof A) {
// large chunk of code
...
} else if (o instanceof B) {
// large chunk of code
...
}
...
} else if (o instanceof H) {
...
}
}
}
In order to split up the method, I'm thinking of extending the Observer interface with e.g. AObserver interface, BObserver interface.. which requires overwriting onAUpdate, onBUpdate .. respectively. This method will also make it easy to determine what Observables the class is observing based on the interfaces it's implementing.
class Foo implements AObserver, BObserver {
....
public void onAUpdate(Observable o, Object param) {
if (o instanceof A) {
// large chunk of code
...
}
public void onBUpdate(Observable o, Object param) {
if (o instanceof B) {
// large chunk of code
...
}
}
The problem is that if I inherit Observer, I still have to implement the update() method. I can't rename it to onAUpdate or some other name of my choosing.
Any advice? Thanks.
I'll suggest to create an UpdateHandler interface to do the processing for any given code block. Each case can be handle with a map.
Sample code follows:
// Interface to implement for each case
public interface UpdateHandler {
public void update(Observable source, Object data) ;
}
Add an instance field to your main class as follows:
private Map<Class<?>, UpdateHandler> handlers = new HashMap<Class<?>, Update Handler>();
Create a method to have the handlers initialized
protected void initializeHandler() {
handler.put(Integer.class, new IntegerUpdateHandler());
handler.put(String.class, new StringUpdateHandler());
...
}
The updates method will simply find the appropriate handler and dispatch the call
public void update(Observable source, Object data)
{
UpdateHandler handler = handlers.get(data.getClass()) ;
if (handler == null)
{
// use a default handler ? throw an exception ? your choice ;)
} else {
handler.update(source, data) ;
}
}
This implementation will allow you to add new handler as needed with minimal changes.
Another possible implementation can be done base on the previous work, just a 3 step procedure.
1) Change the declaration of the handlers field.
Map<Class<?>, Class<? extends UpdateHandler>> handlers ;
2) change the initialize method
handlers.put(Integer.class, IntegerInputHandler.class);
3) change the main update method to create a new instance of the provided UpdateHandler implementation.
UpdateHandler handlerInstance = null ;
Class<? extends UpdateHandler> handler = null ;
handler = handlers.get(data.getClass()) ;
...
handlerInstance = handler.newInstance() ;
handlerInstance.update(source, data) ;
Here I coded a raw implementation using observer and visitor pattern. You can take this as an idea to enhance upon it and to fill wherever you see some holes.
public interface IObserver extends Observer {
public void add(AbstractObservable observable, IObserverVisitor visitor);
public void remove(AbstractObservable observable);
public void removeAll();
}
public class Observer implements IObserver {
Map<AbstractObservable, IObserverVisitor> observableMap =
new HashMap<AbstractObservable, IObserverVisitor>();
public void add(AbstractObservable observable, IObserverVisitor visitor) {
observableMap.put(observable, visitor);
}
public void remove(AbstractObservable observable) {
observableMap.remove(observable);
}
public void removeAll() {
observableMap.clear();
}
public void update(Observable o, Object arg) {
observableMap.get(o).visit(this, o, arg);
}
}
public class AbstractObservable extends Observable{
public synchronized void addObserver(IObserver o, IObserverVisitor visitor) {
o.add(this, visitor);
super.addObserver(o);
}
public synchronized void deleteObservers(IObserver o) {
o.removeAll();
super.deleteObservers();
}
public synchronized void deleteObserver(IObserver o) {
o.remove(this);
super.deleteObserver(o);
}
#Override
public synchronized void deleteObserver(Observer o) {
throw new UnsupportedOperationException();
}
#Override
public synchronized void addObserver(Observer o) {
throw new UnsupportedOperationException();
}
#Override
public synchronized void deleteObservers() {
throw new UnsupportedOperationException();
}
#Override
public synchronized int countObservers() {
return super.countObservers();
}
#Override
public synchronized boolean hasChanged() {
return super.hasChanged();
}
#Override
public void notifyObservers() {
super.notifyObservers();
}
#Override
public void notifyObservers(Object arg) {
super.notifyObservers(arg);
}
#Override
protected synchronized void clearChanged() {
super.clearChanged();
}
#Override
protected synchronized void setChanged() {
super.setChanged();
}
}
public class Observable1 extends AbstractObservable {
public void changeSomething() {
setChanged();
notifyObservers();
}
}
public class Observable2 extends AbstractObservable {
public void changeSomething() {
setChanged();
notifyObservers();
}
}
public interface IObserverVisitor {
void visit(IObserver obsrvr, Observable obsrvable, Object o);
}
public class ObserverVisitor1 implements IObserverVisitor{
public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
System.out.println("updated one");
}
}
public class ObserverVisitor2 implements IObserverVisitor{
public void visit(IObserver obsrvr, Observable obsrvable, Object o) {
System.out.println("updated two");
}
}
public class ObserverTest {
#Test
public void testAnything() {
Observable1 obsrvable1 = new Observable1();
Observable2 obsrvable2 = new Observable2();
Observer obsrvr = new Observer();
obsrvable1.addObserver(obsrvr, new ObserverVisitor1());
obsrvable2.addObserver(obsrvr, new ObserverVisitor2());
obsrvable1.changeSomething();
obsrvable2.changeSomething();
}
}
I hope you are not lost. :)
Move the chunks of code within each condition to appropriately named methods.
public void update(Observable o, Object param) {
if (o instanceof A) {
onAUpdate(o, param);
}
if (o instanceof B) {
onBUpdate(o, param);
}
}
public void onAUpdate(Observable o, Object param) {
// large chunk of code
}
public void onABUpdate(Observable o, Object param) {
// large chunk of code
}