0

I have some code which is time-consuming, you can take it as loading data from disk (but definitely not only that). But I only need this piece of code once in initialization, but it finish, I can use some method related to it directly and quickly.

Now I have no idea where should I put this piece of code, here is my idea: I put it in the constructor in some class A, then in class B, which needs to call some method in A a lot of times, so I make a new instance of A in B's constructor, which is very ideal because each time I need A's method, I can directly access it and A's constructor is only called once.

But here is the problem, I have some other class C, which generate a lot of B instances (new B()), then each time C generates a new instance of B, A's constructor will be called, it is again very time consuming, how can I organize my code to avoid that?

See code for clarification.

class A{
    public A(){
        some time-consuming code; 
    }
    public void methodInA(){
        some method in A;
    }
}

class B{
    public B(){
        A a = new A();
        for (i=0; i<10000;i++)
            methodInB();
    }
    public void methodInB(){
        methodInA();
    }
}
//so far, everything is perfect, but I have another class C 

class C{
    public C(){
        some code;
    }
    public void methodInC(){
        for (i = 0; i<10000; i++)
            new B();
    }

}
user657267
  • 20,568
  • 5
  • 58
  • 77
1a1a11a
  • 1,187
  • 2
  • 16
  • 25
  • Personally, I'd put the code in some method which you can, this provides you with better control over when you might call it, but that's me – MadProgrammer May 28 '15 at 04:30
  • Thanks, suppose I put them in method A, and I only need to call them once (read and process data for another method A) as they are time consuming, but I need to call method B (needs the data from method A) at different places (classes) a lot of times, how do I avoid calling method A multiple times? @MadProgrammer – 1a1a11a May 28 '15 at 04:36
  • 3
    Have one class the loads and processes the data, but returns the result of the data, from which you can pass to other classes/methods. Bit like a Factory Pattern – MadProgrammer May 28 '15 at 04:37
  • 1
    Class A (or at least its expensive disk data) should be instantiated once. Naiively speaking, you could make A a singleton (or a class with static data+fields), then B doesn't call "new A()" but rather "A.instance()". Speaking less naiively I'd use Spring (if you're familiar with Spring terminology, I'll tell spring to create a bean of type "A" with scope=singleton, and inject it into B) – Pelit Mamani May 28 '15 at 04:55
  • Thanks, @MadProgrammer, your suggestion helps and the answer below shows one way to do it. – 1a1a11a May 28 '15 at 13:25
  • @PelitMamani Thank you for your suggestion, when you mention Spring technology, do you mean Spring Framework? – 1a1a11a May 28 '15 at 13:29
  • Yes, Spring framework. Obviously it's just a side remark: button line is just to have 1 instance of the expensive data, and make sure its accessible to other classes - anyway you like. Static variables would be the quickest solution, while Spring offers nicer design patterns at the price of some extra work. – Pelit Mamani May 28 '15 at 18:04

2 Answers2

2

Approach 1: Make methods in class A static and do initialization in static block.

Refer this SO answer.

class A {
    // if any variable then make them static
    static {
        // some time-consuming code;
    }

    public static void methodInA() {
        // some method in A;
    }
}

class B {
    public B() {
        for (int i = 0; i < 10000; i++)
            methodInB();
    }

    public void methodInB() {
        A.methodInA(); // directly call static method
    }
}

Approach 2: Make class A singleton. But that is not recommended in this SO answer by @BalusC.

Community
  • 1
  • 1
Naman Gala
  • 4,670
  • 1
  • 21
  • 55
  • Thank you for your suggestion and example, it is very helpful. – 1a1a11a May 28 '15 at 13:21
  • 1
    For guys who may find this useful, can also check http://stackoverflow.com/questions/335311/static-initializer-in-java, which have some more explanation of the static part. – 1a1a11a May 28 '15 at 13:21
0

So you already identified the problem of putting that "time consuming code fragement" into your constructor of the class A. If the time consuming constructr is being called frequently, so if you generate a lot of Objects of the class a, you will have an overall time consuming program. In your case for example the method

mehodInC(){ 
    //some code
}

Of class C would create 10.000 new B Objects, and since every B Object automatically creates an A Object in the constructor, you would end up calling that time consuming code fragment 10.000 times.

Now this is obviously suboptimal, how could we fix this ? If I were you, I would move that code fragment into a method, since it gives you alot more control over when you wish to invoke it. (Lets call that method methTimeConsuming() for the further argument) It also seperates different functionalities of your program. This can help the overall readability of your final code.

So a way of only calling the time consuming bit of code once, even if you create many objects would be:

A myObj = new A();
myObj.methTimeConsuming();
for(int x = 0; x < 9999; x++){ //9999 because you already called it once outside of for-loop
    myObj = newA();
}

Obvioulsly this is a very basic code fragment, but the idea can be extended from there.

Benjamin
  • 99
  • 8
  • Sorry, when you call new A() inside loop and use its method, the initialization still needs to be done for each instance of A(). – 1a1a11a May 28 '15 at 13:23
  • I'm very sorry, I guess I misunderstood your question. I thought you only needed to call the time consuming code fragment once (after the first initalization), and then not again. My answer then will obviously not help. Then static, as explained above, is the way to go. – Benjamin May 28 '15 at 13:28
  • You are right. I didn't state it very clearly, sorry for my pooooor English. Anyway, I really appreciate your help. – 1a1a11a May 28 '15 at 15:37
  • No worries ! Glad you found a solution dude ! I guess there might be some language barriers on both of our sides ;) – Benjamin May 28 '15 at 17:46