I have following situation and would like to know the best way to design my solution
public abstract class A {
public abstract A getHelper();
public abstract void launchHandle();
public static A initHelper(String condition) throws Exception {
if ( condition == 'xyz') {
return C.getHelper();
} else {
return B.getHelper();
}
}
}
public class B extends A {
protected static A b;
#Override
public A getHelper() {
b = new B();
return b;
}
#Override
public void launchHandle() {
System.out.println("Launching Handle");
}
public String getName() {
return "I am from Class B";
}
}
public class C extends A {
protected static A c;
#Override
public A getHelper() {
c = new C();
return c;
}
#Override
public void launchHandle() {
System.out.println("Launching Handle from C");
}
public String getValue() {
return "I am from Class C";
}
}
**Executor class**
public class Executor {
public static void main(String[] args) {
A aa = a.initHelper(condition);
}
}
Now in the above approach, i am unable to access methods like aa.getName() from Class B OR aa.getValue() from Class C, which makes sense. However how to get these methods in executor class? Executor does not know anything about Class B & C and should not know. Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.
Please help design this and what could be best way to solve this.
Thanks in advance.
Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.
If you take a closer look at your code, you will notice that the only contract constant across all your classes is the launchHandle method (baring getHelper and initHelper which are simply used for instantiating the right subclass). There is no real relation between B and C other than the fact that their instantiation is controlled by A.
This is how I would consider approaching the problem :
Executor Factory
Make Executor an abstract class rather than making it the entry point of your program :
public abstract class Executor {
public abstract void performTask();
public static void execute(String condition) {
Executor executor = null;
if ( condition.equals("xyz")) {
executor = new AExector();
} else {
executor = new BExecutor();
}
executor.performTask();
}
}
Executor implementations
Create a different implementation for operating on B called BExecutor :
public class BExecutor extends Executor {
public void performTask() {
System.out.println("launching handle from B");
//create or get data to perform the task on
B b = new B();
String name = b.getName();
System.out.println("I am from "+name);
}
}
Create a different implementation for operating on C called CExecutor :
public class CExecutor extends Executor {
public void performTask() {
System.out.println("launching handle from C");
//create or get data to perform the task on
C c = new C();
String value = c.getValue();
System.out.println("I am from "+value);
}
}
Your main method can then look like this :
public static void main(String []args) {
Executor executor = Executor.execute(condition);
}
And for some reason, if you do find some common contract between B and C, you an always create an interface which both B and C can implement and use a reference of this interface instead of using a B or C reference.
Add getName and getValue to A as abstract methods.
Related
I'm trying to create some system with inner class. My code can be summarized to something like this.
public abstract class A {
public abstract void doSomething();
}
public class B {
public final ArrayList<A> list=new ArrayList<A>();
public B(){
}
}
public class C {
private int i;
public C(B b){
b.list.add(new A(){
public void doSomething(){
i++;
}
});
b.list.add(new A(){
public void doSomething(){
System.out.println(i);
}
});
}
}
public static void main (String[] arg) {
B manager=new B();
new C(manager);
new C(manager);
new C(manager);
}
A is abstract class that will be inherited as inner class (in my original code it is listener class), B is some kind of manager class that hold list of As, and C hold data it's data should be only modified or read by it's inner class and upon initialization it add A to the class B. Code itself works fine. But problem is as there will be various kinds of C something like C2, C3 that does different thing and this leads to my code overwhelmed with thousands of unassigned object new C(manager); this make debugging extra hard and code looks really ugly. So it seems to me my approach in the first place was wrong but have no idea how to avoid this. So how should I change my approach to not have thousands of unassigned objects?
My suggestion is: try not to use constructors to do operations that depend on state (i). Use static functions, and save the state in a separate class (we call it a “context”).
import java.util.ArrayList;
public class Demo {
// A
abstract static class InnerListener {
public abstract void onEvent();
}
// B
static class ListenerManager {
public final ArrayList<InnerListener> listeners = new ArrayList<InnerListener>();
}
static class SideEffectContext {
public int i = 0;
}
// C
static class ListenerUtil {
public static void setupListeners(ListenerManager manager, SideEffectContext context) {
manager.listeners.add(new InnerListener() {
public void onEvent() {
context.i++;
}
});
manager.listeners.add(new InnerListener() {
public void onEvent() {
System.out.println(context.i);
}
});
}
}
public static void main(String[] arg) {
var manager = new ListenerManager();
var ctxA = new SideEffectContext();
var ctxShared = new SideEffectContext();
ListenerUtil.setupListeners(manager, ctxA);
ListenerUtil.setupListeners(manager, ctxShared);
ListenerUtil.setupListeners(manager, ctxShared);
}
}
I have a basic class structure like this:
public class A {
}
public class B extends A {
private C objC;
public B() {
this.objC = new C();
}
}
public class C extends A {
private B objB;
public C() {
this.objB = new B();
}
}
I need B and C to know about each other so they can access each other's methods but obviously at runtime this creates a cyclic dependency and results in a java.lang.StackOverflowError: null. I have read this and this but I can't seem to get a good resolution on what I should do in my case.
Is there a better way to approach this?
Edit 1: A more descriptive of my situation while keeping simplicity:
public class A {
}
public class B extends A {
private C objC;
public B() {
this.objC = new C();
}
public String foo1() {
int x = C.foo3();
//do something
return Integer.toString(int);
}
public int foo2() {
// do something
}
}
public class C extends A {
private B objB;
public C() {
this.objB = new B();
}
public int foo3() {
int y = B.foo2();
//do something
return y;
}
}
Use Mediator pattern if you want to establish communication among different objects.
Mediator - defines the interface for communication between Colleague objects
ConcreteMediator - implements the Mediator interface and coordinates communication between Colleague objects. It is aware of all the Colleagues and their purpose with regards to inter communication.
ConcreteColleague - communicates with other Colleagues through its Mediator
Have a look at this link : https://en.m.wikipedia.org/wiki/Mediator_pattern
interface Y {
void search(String name);
}
class A implements Y {
void search(String name) {
//Is it possible to say: "If I was called from class B then do a search("B");
}
}
class B extends A {
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search();
}
}
Given the above code is it possible to reason in superclass which subclass was used for calling a method?
The reason I want to do this is because the code in Search is very similar for all Subclasses, the only thing that changes is the Classname, so I thought there is no need to Override in each subclass. I have updated the code to reflect this. Please let me know if there is a better way of doing it/
Calling this.getClass() inside your search method will give you the concrete class of the current instance.
For example:
class Example
{
static class A {
public void search() {
System.out.println(getClass());
}
}
static class B extends A {}
public static void main (String[] args) throws java.lang.Exception
{
new A().search();
new B().search();
}
}
outputs
class Example$A
class Example$B
The cleanest way to do it is to override the method in each subclass.
interface Y {
void search();
}
class A implements Y {
public void search(){
search("A");
}
protected void search(String name) {
// implement your searching algoithm here
}
}
class B extends A {
public void search(){
search("B");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search();
}
}
That's the way inheritance is suppose to works. A super class should not know its subclasses.
And, in case you extends your class B, you can easily either:
-Keep the same behaviour as B:
class C extends B {
// do nothing, when calling search, it calls the method implemented in B
}
-Change the behaviour to search for "C"
class C extends B {
public void search(){
search("C"); // or search("whateveryouwant")
}
}
You can simply override the method in class B.
The other way could be to write the search() method as
void search() {
if (this.getClass().equals(B.class)) {
//The logic for B
} else if (this.getClass().equals(A.class)) {
//The logic for A
}
}
You have to provide the fully qualified name for the class.
Better follow template pattern.
interface Y {
void search(String name);
}
abstract class AbstractionTemplate implements Y{
#Override
public void search(String name) {
//a lot of code.
System.out.println("common stuff start");
doImplspecificStuffOnly();
System.out.println("common stuff end");
//a lot of code.
}
abstract void doImplspecificStuffOnly();
}
class A extends AbstractionTemplate{
#Override
void doImplspecificStuffOnly() {
System.out.println("a's stuff");
}
}
class B extends A {
#Override
void doImplspecificStuffOnly() {
System.out.println("B's stuff");
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.search("hey");
}
}
I want to ask you something more on this matter for the below code for SOLID. If all these 3 classes are are following SOLID concept.
public interface A {
public void calculate(String a);
}
public class B implements A {
#Override
public void calculate(String b) {
System.out.println("value: " + b);
}
}
public class C {
private A a;
public void show() {
a = new B();
a.calculate("test");
}
}
From how I look at things,
Class C breaks the
Single Responsibility Principle by handling two responsibilities, namely, instantiating other objects(instance of B) and the show functionality whatever that is. Object creation should be handled by a separate class and the dependencies should be injected to the users.
Open Closed Principle by being tightly coupled to B, whereas it could have depended on the interface A, thus being open for extension by using another implementation of A. See this for more information. In other words, C should have used A, and the actual implementation should have been injected to C.
Following is how you could write C to be SOLID.
class C {
private A a;
public C(A a) {
super();
this.a = a;
}
public void show() {
a.calculate("test");
}
}
class Creator {
C createC() {
A b = new B();
return new C(b);
}
}
Creator could be replaced by a dependency injection framework like Spring.
I hope the below code snippet is following SOLID strongly.
public class Creator {
public static A getA(){
A a = new B();
return a;
}
}
public class C {
private A a;
public void show() {
setB();
a.calculate("test");
}
private void setB(){
a = Creator.getA();
}
}
I want advice on what should I do:
I have a class A and B such that
public class A {
int result;
int a;
public A(){
result =0;
a = 5;
B myB= new B();
System.out.println(result);
}
public void main(){
A myA= new A();
}
}
public class B extends Thread {
public B(){
start();
}
public void run() {
addition1();
}
public void addition1() {
////////HERE trying to do///////
result = a+5;
}
}
Unfortunally, I need to use, peferable two classes and must two threads and the addition will be perform in the second thread and update the first thread.
This is just an example I came that shows what my issues are. my real code was far too long to post in here.
Thanks
I assume that when you say that you want to update from one thread to another you should have had Class A also as an extension of Thread or a Runnable object. However Class A in your example is not a Thread extension and can be updated by an operation in B (which is another thread) in a usual way like you can update a shared variable in multi threaded scenario. Just expose a setter method for the result variable in Class A and update it from the B class method (addition1) which is running in new thread. Therefore you would have updated a shared instance (of class A) being operated upon by main thread (the first thread) from another thread (spawned during construction of Class B) method (addition1)
You can try with Callback Mechanism to get the result back one it's computed.
For more info read inline comments.
Sample code:
interface Callback {
public void execute(int result);
}
// make it abstract and don't provide implementation of execute method here
abstract class B extends Thread implements Callback {
private A a;
// pass the reference of Class A to access it
public B(A a) {
this.a = a;
start();
}
public void run() {
addition1();
}
public void addition1() {
int result = a.a + 5;
//result is computed now call pass the value to the waiter and that's A
execute(result);
}
}
class A {
int result;
int a;
public A() {
result = 0;
a = 5;
B myB = new B(this) {// pass the reference of Class A
#Override
public void execute(int result) {
// This is the computed result that is returned from Class B
System.out.println(result);
}
};
}
}