0

This is a interview question I was asked a week back, The problem was that

You have to develop a music player which gives the user the ability to create a new theme and use it.

I said that let's say there is a theme class like this

Class theme{ par1;
par2;
par3;

getter,setter

}

When the user tells our player to create a new theme, we will ask for these parameters and by using setter, we can have a theme object with parameters than can be used for rendering.

However he told me that this a java reflection question, he said you are supposed use reflection to get the class name etc.

Does anybody have any idea how reflection can be used here? or Have they ever been asked a question similar to this? Did they use reflection for solving?

I think it might have something to do with Factory design pattern but I can't find similarities between the question given and the design pattern?

Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
Max
  • 9,100
  • 25
  • 72
  • 109

2 Answers2

1

What could be meant is class loading - to dynamically load the theme which also includes class loading - you get the needed class by calling Class.forName("org.package.YourTheme") and then create new instance by using reflection. And this instance or a plugin could customize your app.

EDIT:

This is how usually plugins are done in Java application. The developer creates a JAR containing it's implementation. In the simple case scenario he extends an interface in the app:

    interface Theme{
        void initialize();
        void handleEvent(AppEvent e);
    }

    class MyTheme implements Theme{
        public void initialize(){
            // init logic
        }

        public void handleEvent(AppEvent e){
            // handles the event
        }
    }

These two classes are packed by the developer into my-theme-0.1.jar.

A user downloads them on the web and copies them into the themes folder of his app.

When the app starts (or this could also be done during runtime) it scans the themes folder and loads all plugins by using URLClassLoader.

Then you load your theme:

    final Class<?> settingsClass = classLoader.loadClass("MyTheme");
    Theme theme = (Theme) settingsClass.newInstance();

    theme.initialize();
Community
  • 1
  • 1
Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
  • But I don't have that class in the workspace right, this is supposed to be created on runtime? Can you give the flow of what you are saying in your post? – Max Sep 23 '13 at 16:50
  • Edited the post to add an example. – Andrey Chaschev Sep 23 '13 at 17:14
  • oK, what I meant was, there is web music player and the user uses the UI of the app to create a new theme. User can't get the access of the source code, all he has is few controls to give the parameters of the new theme. When he submits his request, then in a way new class is formed with or without reflect? At least that is what my understanding is. Does it make sense? – Max Sep 23 '13 at 17:28
  • Yeah, it does. This nearly how it is done in [Jenkins](https://wiki.jenkins-ci.org/display/JENKINS/Simple+Theme+Plugin). – Andrey Chaschev Sep 23 '13 at 17:45
  • Ok, so I think all it comes down to is 'how we are going a create a class in the bakcend' right? I looked that up, and it seems that is some other technique, so can't do that with reflection? So how it it that through reflection we will create it? – Max Sep 23 '13 at 18:01
  • aClass.newInstance() is the method to create an instance of a class. And you get the this Class from the classloader. The full sequence is `theme = new URLClassLoader(...).loadClass(...).newInstance(params)`. – Andrey Chaschev Sep 23 '13 at 19:19
  • I am extremely sorry for the deadlock, but Don't we need the class definition of my user_theme to achieve what you just said. "new URLClassLoader(...)" needs the path of the class the user is supposed to create? My question was not that how to get the instance from a class but "How to create a class when user has given just the perimeters". – Max Sep 23 '13 at 19:40
  • If I understand you right, the parameters are the theme name, right? So at the startup themes' JARs are loaded into the app and each theme name is associated with it's containing JAR. When you switch a theme, the app searches for a JAR by a theme name (could be a simple Map entry) and creates a new instance of a theme. This could be one of the ways to achieve this. – Andrey Chaschev Sep 23 '13 at 19:56
  • Ok I got it now, My question is that I want to create a new theme whose class or jar does not exist, it could be similar to existing theme but may be the color is different. That is the exact interview question. By parameters I mean theme size, color, edges aspects of theme just for an example. So when the user provides everything for a theme, we should use that data to create a theme and install in the system. – Max Sep 23 '13 at 20:02
  • This is a really strange question if it suggests using reflection. Usually if you want to modify a theme, you just copy it and modify the HTML/CSS. The only context which makes sense for me is developing a Swing app. – Andrey Chaschev Sep 23 '13 at 20:18
0

I think one possible the solution could be as follows:

We'll use reflection to get all the attributes, these attributes would then be used to bring the customizable parameters up to the user.

Let's assume this is our theme class:

Class Theme{ 
    //Customizable Theme related attributes
    private Color background;
    private Color baseColor;

    //Business Domain related attributes
    private User user;

}

We can use reflection to get the list of attributes Theme::getDeclaredFields, then we can get their names and inform the user about these attributes and "ask" him for what values he wants to customize.

The problem here is our class have attributes that aren't relevant to the theme 'look & feel' fields. For example the theme user field (owner?) shouldn't be brought to the user. This problem can be solved by using annotations (>= JDK 1.5)

Our class would then look like this :

Class Theme{ 
    //Customizable Theme related attributes
    @LookAndFeel(alias="Background", description="The background color of the player")
    private Color background;

    @LookAndFeel(alias="Base Color", description="The base color of the player")
    private Color baseColor;

    //Business Domain related attributes
    private User user;

}

Now using reflection again we can bring up only the Look and feel related attributes (by inspecting the annotations), and we have as a bonus a user-friendly information about the fields : Ex. we will be able to tell the user that there is some "Base Color" parameter (better than using our attribute name "baseColor") that he can adjust.

yechabbi
  • 1,881
  • 17
  • 14