0

So I have this code that applies a number of filters on a live camera preview. The frame is drawn on a Texture view on the onSurfaceTextureUpdated.

I have a listView that the user clicks on an item. That item depending on it's position, if it is 3 for example it will invoke filter 3.

Now the problem is that in my onSurfaceTextureUpdated as you can imagine I have a big switch statement. I was wondering if I could refactor it to a better structure. Can I use something as EventListener or anything else??

Here is part of my code (just imagine some random code inside the cases)

public void onSurfaceTextureUpdated(SurfaceTexture surface) {

bmp = mTextureView.getBitmap();
bmpCopy = bmp.copy(bmp.getConfig(),true);

switch(processingFunction){
    case 0: 

        break;
    case 1: 

        break;
    case 2: 

        break;
    case 3: 

        break;
    case 4: 

        break;
    case 5: 

        break;
    case 6:

        break;
    case 7: 

        break;
    }
}

Now in each case there is some code which I was too lazy to include. This will grow. Imaging having 30+ functions. I don't want to end up with a huge file. So what is the alternative?

Trt Trt
  • 4,764
  • 11
  • 46
  • 77

3 Answers3

3

If I understand your question correctly, you want to look at Factory Pattern

You might have to create 30+ classes(depending on your number of cases) but this is a clean approach, easy to maintain and produces readable code. Adding or removing a Filter is also easy, Just remove the class and remove it from FilterFactory hashmap.

Create an Interface : Filter

 public interface Filter {
    void Filter();
 }

Create a Factory which returns correct Filter according to your processingFunction. Instead of your switch case now you can just use the following :

  Filter filter = FilterFactory.getFilter(processingFunction);
  filter.filter();

One common way to write FilterFactory is using a HashMap inside it.

public class FilterFactory{
   static{
     HashMap<Integer, Filter> filterMap = new HashMap<>();
     filterMap.put(0,new Filter0());
     ...
   }
   // this function will change depending on your needs
   public Filter getFilter(int processingFunction){
       return filterMap.get(processingFunction);
   }

}

Create your Filters like this: (With meaningful names though)

public class Filter0 implements Filter {

    public void filter(){
      //do something
    }
}
Karthik
  • 4,652
  • 4
  • 27
  • 62
2

I seriously don't understand why people are talking about using Reflection to simplify code ?

Your problem is a typical case to apply the strategy design pattern: https://en.m.wikipedia.org/wiki/Strategy_pattern

The Wikipedia article will explain it better than me. In your case you want to create a Filter interface where one of the abstract method is the processing function. Another one could return the filter name and description.

You probably already have Filter objects in your application model, in order to be able to show them to the user so (s)he can select them. Make sure you you make them all implement the same interface so your code can treat any of them in a generic way.

BladeCoder
  • 11,697
  • 2
  • 51
  • 46
  • I will this a go to. I am not looking into making my code faster, just faster – Trt Trt Jul 04 '15 at 13:50
  • This will make the code both faster and easier to maintain. Another person here mentioned the Command pattern which is not exactly the same thing. Command pattern is a way to store an abstract action and its parameters in an object and it usually has only two methods without arguments: execute() and undo() and is mostly used to implement a history or a work queue. – BladeCoder Jul 04 '15 at 14:44
1

I assume that you want something like array of methods. There are two ways of achieving this. First way is by using reflection. It requires less coding, but reduces performance, since reflection in java is performance greedy. Second way (more preferable) is Command Pattern. I've had situation like yours and tested reflection vs command pattern performance. Command pattern is about 30 - 50ms faster per 1000 calls. It may seem not a big difference, but you can notice it if your program will call that methods frequently (graphics updating, modules interaction etc. .)

CommandPattern

Processor

interface ProcessorMethod{
  public void invoke();
}

ProcessorsFactory

class ProcessorsFactory{

  private Processor processor;      
  private HashMap<Integer, ProcessorMethod> processors;

  public ProcessorsFactory(Processor p){
    processor = p;
    processors = new HashMap<>();

    processors.put(new Integer(0), new ProcessorMethod(){
                                        @Override
                                        public void invoke(){
                                         processor.processFunction_0();}
    });


    processors.put(new Integer(1), new ProcessorMethod(){
                                        @Override
                                        public void invoke(){
                                         processor.processFunction_1();}
    });
                                   .
                                   .
                                   .
  }    


 public ProcessorMethod getProcessor(int processorIndex){
   return processors.get(new Integer(processorIndex));
}

Processor

class Processor{

  public void processFunction_1() {.......}

  public void processFunction_2() {.......}
     .
     .
     .
}

Some Class

 Class SomeClass{

  ProcessorsFactory factory;
  Processor processor;

  public SomeClass(){
    processor = new Processor();
    factory = new ProcessorsFactory(processor);
  }

  public void doSomething(int processingFunction){
    factory.getProcessor(processingFunction).invoke();
  }

}

Reflection

ProcessorsFactory

    class ProcessorsFactory{
       private HashMap<Integer, Method> processingFunctions = new HashMap<>();

      public ProcessorsFactory(Processor processors){
          Class processorsClass = processors.getClass();
          int count = 0;
          for(Method m : processorsClass.getDeclaredMethods())
            if(m.getName().startsWith("processFunction")
                processingFunctions.put(new Integer(count++), m)
          }               
      }

      public Method getProcessor(int processorIndex){
          return processingFunctions.get(new Integer(processorIndex))};

    }

Processor

class Processor{

  public void processFunction_1() {.......}

  public void processFunction_2() {.......}
         .
         .
         .
}

SomeClass

Class SomeClass{

ProcessorsFactory factory;
Processor processor;

  public SomeClass(){
    processor = new Processor();
    factory = new ProcessorsFactory(processor);
  }

    public void doSomething(int processingFunction){
      factory.getProcessor(processingFunction).invoke(processor, arg1,   arg2. . .)
    }

}

If you will not gonna use these methods very frequently, fell free to use Reflections. If you want better performance, choose Command Pattern.

P.S This is not copy-paste pieces of code, but principles, that I know and had used. You should refactor it by your needs. I recommend you to learn Design Patterns. Derek Banas youtube chanell is a good place to start. He know how to explain such things. Cheers :)

callOfCode
  • 709
  • 6
  • 10