design pattern for parent-child structure - java

I'm working on a project using JavaFX and classes have typically as many as 800-1200 lines . We are using fxml for displaying Node elements, still this classes are very complex. Here is concretely what I ask:
A class ReservationUI contains sub parts , which are modulerized as inner classes at the moment.which again has sub parts. And this classes has access to fields of ReservationUI . Now I like to extract them to their own classes but now I need to have access to parent class .
class A{
int x; int y;
B b;
public A(){
b = new B();
b.display();
}
private class B{
private C c;
/* modify x */
}
private class C{
/* modify x and y */
}
}
And when i extract them now I have dependencies even worse :
class A {
int x; int y;
B b;
public A(){
b = new B(this);
b.display();
}
}
class B {
C c;
A a;
public B ( A parent ){
c = new C(this, parent);
a = parent;
/* call A.modifyX(c.get) */
}
class C{
A a;
B b;
public C( B parent , A root){
a = root;
b = parent;
}
}
What I think is here the modularization is gone terribly wrong. Especially when I have relations long as this one : root -> child -> child -> child ... .
Is there a design pattern to address this issue. As far as I know there is Mediator pattern but use of it, still doesn't bring much since I still need to basically do the same thing .

The best way to do this, is to use some kind of dependency injection. The controller then resolves dependencies automatically. I assume that you don't need any enterprise framework that provides it, so you have to resolve dependencies manually somehow.
The purpose of mediator pattern is to simply encapsulate dependency mamagement in one single place. In my solution, root element A acts just as mediator. Side offect of it, is that child elements exist in short period in an uninitialized state. To solve this issue you can also introduce Builder pattern.
interface IA{
/*...*/
void modifyX(int x);
}
class A implements IA{
int x; int y;
IB b;
IC c;
public A(){
b = new B();
c = new C();
resolveDependencies();
b.init();
b.display();
}
public void resolveDependencies(){
b.setC(c);
b.setA(this);
c.setA(this);
c.setB(b);
}
}
interface IB {
void setC(IC c);
void setA(IA a);
void init();
void display();
}
class B implements IB{
IC c;
IA a;
public B (){
}
#Override
public void setC(IC c){
this.c = c;
}
#Override
public void setA(IA a){
this.a = a;
}
#Override
public void init(){
/* call A.modifyX(c.get) */
}
}
interface IC {
void setA(IA a);
void setB(IB b);
}
class C implements IC{
IA a;
IB b;
public C( ){
}
#Override
public void setA(IA a){
this.a = a;
}
#Override
public void setB(IB b){
this.b = b;
}
}

Related

Avoiding Dynamic Type Casting with Inheritance for Data Classes in Java

I have 3 Data Classes
#Data
class A
{
private int a;
}
#Data
class B extends A
{
private int b;
}
#Data
class C extends A
{
private int c;
}
Class B and C have some common fields between them which is kept in their parent class A.
Following is the tester class
class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args) // assume this to be the client
{
A a;
if (bOrC.equals("B")) {
B b = new B();
b.setB(11);
a = b;
} else {
C c = new C();
c.setC(12);
a = c;
}
a.setA(10);
doSomething(bOrC, a);
}
// Below are the service methods
// only this method in the service exposed
public static void doSomething(String bOrC, A a) {
if (bOrC.equals("B")) {
doSomethingWithB(a);
} else if (bOrC.equals("C")) {
doSomethingWithC(a);
}
}
public static void doSomethingWithB(A a) {
B b = (B) a; // possible ClassCastException
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(A a) {
C c = (C) a; // possible ClassCastException
System.out.println(c.getA());
System.out.println(c.getC());
}
}
Now the problem I see with this is unsafe Dynamic Type Casting which can run into Class Cast Problems. One possible solution would be to create separate data objects and set the common fields (which are too many for my actual case) for both the objects separately in both classes B and C which would then look as follows:
public class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args)
{
if (bOrC.equals("B")) {
B b = new B();
b.setA(10); // duplication
b.setB(11);
doSomethingWithB(b);
} else {
C c = new C();
c.setA(10); // duplication
c.setC(12);
doSomethingWithC(c);
}
}
public static void doSomethingWithB(B b) {
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(C c) {
System.out.println(c.getA());
System.out.println(c.getC());
}
}
I'm looking for a way to avoid this dynamic type casting but at the same time avoid having to duplicate the common variables. Can anyone suggest a solution?
Abstraction is one solution for the behavior you are explaining. Creating an abstract method doSomething(...) in class A and implementing it in child class B and C respectively. By doing this you don't need to have a static method and processing will be done bases on the instance of B or C objects itself.
#Data
class A
{
private int a;
public abstract void doSomething();
}
#Data
class B extends A
{
private int b;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to getA() method, * hence you can also use parent properties.
*/
}
}
#Data
class C extends A
{
private int c;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to
* getA() method, * hence you can also use parent properties.
*/
}
Now you can use it as below
public static void main(Strings[] args){
A a;
B b = new B();
b.setB(10);
b.doSomething();
C c = new C();
c.setC(30);
c.doSomething();
}

Creating instance of member variables

Hi this is a basic question, but kindly bear with me.
I have two classes and on class has a reference of another class. How can i create the instance of second class which is present in first class at the time creation of instance of first class. Are any utility present for this.
Code ::
class A {
B b;
}
class B {
int member;
}
In a Contructor (like Robert Kock already said)
class A {
B b;
public A(){
b = new B();
b.member = 5;
}
}
Directly as Attribute
class A {
B b = new B(5);
}
With Initializer
class A {
B b;
{
b = new B();
b.member = 5;
}
}
Within the constructor of the first class:
class A
{
public A()
{
b = new B();
}
B b;
}
Or even like this:
class A
{
public A()
{
}
B b = new B();
}
A general solution would be:
public class A {
private final B b;
public A(B b) {
this.b = b;
}
}
...
A a = new A(new B());
It becomes interesting when both instances refer to each other, then you need to use a setter in at least one of the classes:
public class B {
private A a; // the field cannot be final in this case
public void setA(A a) {
this.a = a;
}
}
....
B b = new B()
A a = new A(b);
b.setA(a);
The answers where the class is creating the other instance itself are not a general solution.

Constructor arguments in subclass

I have a question which might be a very simple one but I can't find the way out.
Here are the Parent and Child classes which will work without a problem.
public class Parent {
private A a;
private B b;
Parent (A a, B b){
this.a = a;
this.b = b;
}
public class A {}
public class B {}
private class C {}
public class Child extends Parent {
private final C c;
Child(A a, B b, C c,) {
super(a, b);
this.c = c;
}
}
}
Here is the problem: Fields b and c are fields of some other class ClassBC and ClassBC is one of the argument of class Child. i.e.,
public class Child extends Parent {
private D d;
Child(A a, C c) {
// I must call super(...) here; but can't do that without `b`
ClassBC classBC = new ClassBC(c);
B b = classBC.getB();
D d = classBC.getD();
}
// some methods
}
private class ClassBC{
private D d;
ClassBC(C c){
// do something here to get 'B' and 'D'
}
public D getd(){
return d;
}
public B getB(){
return b;
}
}
So:
Am I being stupid or breaking some rules here?
I tried to use Builder in Parent class such that it can be used in the constructor of Child class. As expected, it compiled but failed because fields of Parent classes are not available in Child class.
I want to avoid using builder in Child class because it will lead to too may changes in the repository. What else I can try?
This is a minimal example, actual classes are complex with couple of more arguments.
Cant you do it with factory method. Make Child constructor private, and add static method createChild create child objects from this factory method.
Create your ClassBC objects before calling Child constructor.
I think that should work for you
public class Child extends Parent {
private D d;
private ClassBC bc;
Child(A a, C c) {
// Inline
this(a, new ClassBC(c));
}
Child(A a, ClassBC bc) {
super(a, bc.getB());
this.bc = bc;
this.d = bc.getD();
}
}

How do we make a java class immutable if it has a member variable of another user defined class?

Recently in an interview for Java Developer role, I was asked how do I make Class A immutable if it has a member variable, which is an object of Class B and in a situation where Class B is external to the project and cannot be edited by the programmer moreover class B might even have a member variable of its own which is an object of another user defined class. I gave it a lot of thought and told the interviewer there is no way unless class B has implemented and exposed a method to deep clone itself.
The interviewer though wasn't convinced. Is there really a way to make such a class immutable?
If I can remember correctly this was the situation he explained. He wanted me to make class A immutable, what would have been the best answer?
final public class A {
final private B b;
A(B b) {
this.b = b; // Class b might/might not be cloneable
// this.b = (B)b.clone();
}
public B getB() {
return b;
// return (B)b.clone();
}
}
class B // external cannot edit
{
C c;
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
}
class C // external cannot edit
{
int i;
String j;
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
public String getJ() {
return j;
}
public void setJ(String j) {
this.j = j;
}
}
Don't expose B to the world. So do not have a method which return B.
Instead identify the methods in B, which don't mutate B and let A implement these methods by calling the same method in b.
So if B has a method calcSomething() a should have a calcSomething() methocd which just does return b.calcSomething().
You may use something like this:
final public class A {
final private B b;
A(B b) {
this.b = cloneB(b);
}
public B getB() {
return cloneB(b);
}
private static B cloneB(b){
B newB = new B();
C c = new C();
c.setI(b.getC().getI());
c.setJ(b.getC().getJ());
newB.setC(c);
return newB;
}
}
It that case Class A is 100% immutable.
Update: Also you can use reflection or seralization to get deep copy of class (if class has deep hierarchy), for example using GSON for seralization:
private static B cloneB(b){
String tmp = new GSON().toJson(b);
return new GSON().fromJson(tmp, B.class);
}
or so on

If all these 3 classes are following SOLID concept

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();
}
}

Categories