I'm learning Java and I'm fairly new to this. Here is my problem with some pseudocode:
public void objectCaller(int objectNumber) {
switch(objectnumber) {
case 1:
object1.setFill(color.RED);
break:
case 2:
object2.setFill(color.RED);
break;
.
.and so on
}
}
Is there a way to replace it in a way with something like that?
public void objectCaller(int objectNumber) {
(object + objectnumber).setFill(color.RED);
}
It is not a concrete problem. I was just thinking about if it is possible to assemble the object names.
There are three approaches you can use to solve the problem (Reflection is the last option I would recommend) :
Option 1 : Employ the Strategy pattern
If method1 and method2 are not objects of classes that are related. Employ the Strategy pattern as follows :
public interface Filler {
public void fill(Color color);
}
Create two classes that fill colors differently :
public class FloodFill implements Filler {
public void fill(Color color) {
//fill using flood fill algorithm
}
}
public class QuickFill implements Filler {
public void fill(Color color) {
//fill using quick fill algorithm
}
}
You can then use the Map approach explained below :
Option 2 : Use a HashMap
Assuming that method1 and method2 are related either through a common parent or through a parent child relationship, create a HashMap and prepopulate it with method1 and method2 objects :
Map<String,Filler> methods = new HashMap<>();
FloodFill method1 = new FloodFill();
QuickFill method2 = new QuickFill();
map.put("FloodFill",method1);
map.put("QuickFill",method2);
You can then change the methodCaller method to :
public void methodCaller(String method,Color color) {
methods.get(method).fill(color);
}
The client code can then look like this :
methodCaller("FloodFill",Color.RED);
methodCaller("QuickFill",Color.GREEN);
Using a HashMap instead of a basic array or a List allows you to associate meaningful names to your method calls. The HashMap is kind of a Factory for objects. The String constants used as the key for the Map can be defined as enum instead.
Option 3 : Use reflection :
This is not something I would recommend for this particular case but if you have to, take a look at this answer on how to achieve this trough reflection.
You could do that by reflection, but for this case is clearly overkill.
What about this approach?: Store your objects in an array (or a List) and then use the index to access the required one.
Note that I'm assuming that all the objects are of the same class or are least they have a parent-child class relationship, as #ChetanKinger pointed in the comment below.
public void methodCaller(int methodNumber) {
myArrayOfObjects[methodNumber].setFill(color.RED);
}
PS: In fact, you are trying to compose "object" names, not methods names. In that case you would really need to use the Reflection API
Related
I'm receiving from a webservice a list of key-value pairs, and have inherited the following code:
public String iconValue = null;
... (over 50 class variables assigned in MyObject constructor below)
public MyObject(List<Attribute> attrs) {
String attrName, attrValue;
for (Attribute a : attrs) {
try
{
attrName = a.getName();
attrValue = a.getValue();
if (attrValue == null || "".equals(attrValue.trim()))
continue;
if (ICONS.equals(attrName)) {
//Do something including assignment
this.iconValue = attrValue;
}
else if (URL.equals(attrName))
{
//Do something including assignment
}
else if (...) A giant list of over 50 different attributes hardcoded
{
//Do something including assignment
}
...
So,except for keeping a hashmap - is there a better way than the above to keep hard coded variables within the class and use this "when-if" pattern.
Also,does this pattern have a name?
One way I can think about is to use ENUMs and dynamically dispatch the works to each of the ENUM object, instead of doing a huge if else, esp. since ENUMs can be looked up by their names.
That would be like a strategy pattern.
For example:
Implement an ENUM to have a method doJob() for each of the instances;
Use the valueOf() method to dispatch the works.
Code sample:
public enum Strategies {
URL {
#Override
public void doJob(MyObject mo) {
// do the work
}
},
ICONS {
#Override
public void doJob(MyObject mo) {
// another work
}
};
public abstract void doJob(MyObject mo);
}
And when using it,
try {
Strategies.valueOf(attrName).doJob();
} catch (IllegalArgumentException e) {
// ENUM does not exist, illegal parameter
}
If you want to take a different action for each possible value of attribute, you will end up with something about that verbose, I'm afraid. Some improvements though:
If you are using Java7 or above, you can now use switch statements with Strings (link)
If you are not, you could create an Enum that has a static method that returns an Enum element you could switch on. It's no performance improvement, but it might help with readability of your code.
Does this pattern have a name?
Nope.
In Java 7 you can express that as:
switch (attrName) {
case ICONS:
//Do something including assignment
break;
case URL:
//Do something including assignment
break;
// and so on
}
... provided that ICONS, URL and the other strings are compile-time constants.
That is more concise and more robust. It is also (probably) more efficient because the switch can most likely be implemented using hashing.
I don't think it has a name, but you could call it "using polymorphism wrong" (if type safety is a concern). It depends on whether you have a well defined data contract or not. Is the data you're receiving a proper object, or just "random" data?
If it's a proper object I would create a concrete representation and use something like Dozer (or if you don't want to be tied down wit dependency, roll your own mapper using reflection) to convert between them.
If it's more or less random data, I'd just use a Map, or similar data structure.
I have written a Java enum where the values have various attributes. These attributes could be stored in any of the following ways:
Using fields:
enum Eenum {
V1(p1),
V2(p2);
private final A attr;
public A attr() { return attr; }
private Eenum(A attr) {
this.attr = attr;
}
}
Using abstract methods:
enum Eenum {
V1 {
public A attr() { return p1; }
},
V2 {
public A attr() { return p2; }
}
public abstract A attr();
}
Using class level map:
enum Eenum {
V1,
V2;
public A attr() { return attrs.get(this); }
private static final Map<Eenum, A> attrs;
static {
ImmutableMap.Builder<Eenum, A> builder = ImmutableMap.builder();
builder.put(V1, p1);
builder.put(V2, p2);
attrs = builder.build();
}
}
How should I decide when to prefer which?
Thanks!
I would do the one which you think is the simplest.
In general I don't write code which can be implemented using data. I would use the first one.
My actual use case has some attributes which are not relevant for all enum values
You can use a combination of these approaches if it makes sense on a per attribute basis.
A fourth option is to not have an abstract method.
enum Eenum {
V1 {
public A attr() { return p1; }
},
V2 {
public A attr() { return p2; }
},
V3, V4, V5, V6;
public A attr() { return defaultA; }
}
None of those. Do this:
interface HasAttr<T> {
T attr();
}
enum Eenum implements HasAttr<A> {
// use "fields" version - ideally with constructor version
public A attr() {
return field;
}
}
This pattern follows the fundamental Abstract Type design pattern, which allows for method like:
public void someMethod(HasAttr<A> hasAttr); // pass anything that is HasAttr<a>
in preference to the fixed type:
public void someMethod(Eenum eenum); // locked into passing an Eenum
Also, and importantly, it's easier to mock for testing, especially if your enum uses real connections etc.
I grant you, all this only applied if the enum is "nontrivial". If it's just a plain old enum, I agree it's just code bloat (which I also detest)
(I am answering my own question so that I can share some things I learned while trying out things.)
Here are the questions you should ask to come at a decision for your specific case:
1: Do the attribute values involve forward references?
Sometimes V1's attribute may need a reference to V2 and vice versa. This is not a rare case. If you are dealing with such an enum, approach 1 simply would not work. The compiler will (rightly) complain about illegal forward references. Any of the other two approaches can be used.
Now, if the attribute value is expensive to compute and a constant, you'd want that it's computed only once. With approach 2, you'd have to introduce local variables per enum value, and cache results there. This is verbose but will give you better performance. With approach 3, the results are anyway computed only once, and so don't have to do any extra work. This is more readable but somewhat less performant than approach 2. Design between these as per the specific trade offs warranted in your case.
2: Do I need to cache results?
Refer to the second paragraph of previous bullet.
If there are no forward references, you can use approach 1 too. But if the computation involved in calculation of attributes is complex, you are better off with one of the other two approaches.
3: Are the attributes relevant for all of the enum values?
If not, then quite logically, you should be using a Map here. That is, approach 3.
4: Are there any default values for some attributes for some enum values?
If so, you can use all three approaches, and they all offer different set of trade-offs.
With approach 1: You would define an auxiliary constructor that initializes the attribute to the default value. If there are multiple such attributes, this might not be a feasible approach.
With approach 2: This will actually be like "fourth" approach Peter Lawrey suggested above. You will have a method returning the default value in enum's main body. And some enum values will override this method to return a different value. This is, again, quite verbose.
With approach 3: Just less efficient. Good in every other way.
I have a list of MyObjects which I need to divide into three groups:
Known good (keep)
Known bad (reject)
Unrecognized (raise alert)
MyObject contains various properties which must be examined to determine which of the 3 groups to put the object in.
My initial implementation (Java) just takes a List in its constructor and does the triage there. Pseudocode:
class MyObjectFilterer {
public MyObjectFilterer(List<MyObject> list) {
// triage items here
}
public List<MyObject> getGood() {
// return sub-list of good items
}
public List<MyObject> getBad() {
// return sub-list of bad items
}
public List<MyObject> getUnrecognized() {
// return sub-list of unrecognized items
}
}
Any issues with this implementation? Is there a better OO choice?
I would probably prefer a static factory method to do the filtering, that then calls a private constructor that takes the three filtered lists, following the good code practice of never doing any serious work in a constructor. Other than that, this looks fine.
There may be multiple approachs. If the problem is generic / repetitive enough, you could define an interface with a method to classify the objects.
interface Selector {
public boolean isGood(MyObject myObject);
public boolean isBad(MyObject myObject);
public boolean isUnknown(MyObject myObject);
}
That way you could change the logic implementation easily.
An other idea would be using the Chain of responsibility.
Your MyObjectFilterer contains a reference to three Objects GoodFilterer, BadFilterer and UnrecognizedFilterer. Each of them contains the following methods: addMethod(MyObject object), getObjects() and addFilter(). Of course they have to implement an interface Filterer.
With the addFilter method you can build the chain. so that the GoodFilterer contains a reference to the BadFilterer and this one contains a reference to the UnrecognizedFilterer
Now you go through your list of MyObjects and call the add method on the GoodFilterer (first one in this chain). Inside the add method you decide if this is good, than you keep it and finish the work, if not pass it on to the BadFilterer.
You keep your three methods for getting the good/bad and unrecognized, but you will pass this to the getObjects() method of the corresponding Filterer
The Benefit is that the logic if this is a good/bad or Unrecognized one is now seperated.
The Downside you would need 3 new classes and 1 Interface.
But like i said, this is just an other idea what you could do.
You should simplify as it's possible. Just make static method in MyObjectFilter with following signature:
public static List filterMyObjects(List data, Group group).
Group is enumeration with three values and it can be used as attribute of MyObject class
I might try something like:
enum MyObjectStatus {
GOOD, BAD, UNRECOGNIZED;
}
class MyObjectFilterer {
private MyObjectStatus getStatus(MyObject obj) {
// classify logic here, returns appropriate enum value
}
// ListMultimap return type below is from Google Guava
public ListMultimap<MyObjectStatus, MyObject> classify(List<MyObject> objects) {
ListMultimap<MyObjectStatus, MyObject> map = ArrayListMultimap.create();
for(MyObject obj: objects) {
map.put(getStatus(obj), obj);
}
}
}
Call classify() to get a Multimap, and extract each category as needed with something like:
List<MyObject> good = map.get(GOOD);
List<MyObject> bad = map.get(BAD);
List<MyObject> unknown = map.get(UNRECOGNIZED);
A nice thing about this solution is you don't have to create/publish accessor methods for each category (unless you want to), and if new categories are created, you also don't add new accessors -- just the new enum and the additional classifier logic.
I would have a string that is parsed into an array, as shown here:
class Example extends ParentClass {
private String[] array;
public static Example parseString(String lineToParse) {
array = lineToParse.split("\");
}
public ObjectType1() { // arguments: String, String, String
}
public ObjectType2() { // arguments: String, String, String, double, double
}
}
What I'm wondering is could I do this?
if (array[0].equals("Test")) {
public ObjectType1()
}
Or is there a better way to do this?
I want to create various objects with different arguments each, and the first argument (array[0]) will be applicable to each object, so I was wondering if I could create objects within an if statement like this, or a switch (not sure if that would work either).
I believe a factory method would be useful for you, one that returns instances of classes according to the parameter received:
// ObjectType1, ObjectType2, ObjectType3 inherit from ObjectType
static ObjectType getInstance(String[] array) {
if (array[0].equals("Test"))
return new ObjectType1(array);
else if (array[0].equals("Test2"))
return new ObjectType2(array);
else
return new ObjectType3(array);
}
For the record, actually you can define a class inside a method, this is valid code in Java ... of course, that's hardly a good thing to do:
// ObjectType1, ObjectType2 inherit from ObjectType
public ObjectType example(String[] array) {
if (array[0].equals("Test")) {
class ObjectType1 {
ObjectType1(String[] array) {
}
}
return new ObjectType1(array);
}
else {
class ObjectType2 {
ObjectType2(String[] array) {
}
}
return new ObjectType2(array);
}
}
"Creating" an object means "instantiating it", with new:
ObjectType1 foo = new ObjectType1(...);
You can do that anywhere it's legal to instantiate a class, including in an if statement.
You cannot define classes in arbitrary locations, however.
If you just want to call a method (which should start with a lower-case letter if you want Java developers to understand what you're trying to do), you can call it from anywhere, including inside if statements.
This sounds like you may want to use a [static factory method][1].
[1]: http://en.m.wikipedia.org/wiki/Factory_method_pattern
I guess that you want to dynamically create objects based on a configuration file?
There are lots of ways to achieve this. One simple way is to use reflection to create the objects. Then you do not need any if/switch statements, and if you want to create a new type of object your code does not need to be changed.
Here are some examples for using reflection: Reflection API Code Samples
I have an enum like
public enum Field {
A, B, C, D, E ....;
private Field(){
}
}
I have a class Panel that takes Field array to initialize the fields:
public class Panel {
TextBox A;
TextBox B;
TextBox C;
TextBox D;
TextBox E;
...
public Panel(Field[] fields){
this.fields = fields;
init();
}
public void initA(){}
public void initB(){}
public void initC(){}
public void initD(){}
public void initE(){}
}
My question is, how can I initialize the fields that given without writing many if statement?
I can't find any solution and I'm now initializing like this:
public void init(){
for(int i = 0 ; i < fields.length; i++){
if(fields[i] == Field.A){
initA();
} else if(fields[i] == Field.B){
initB();
} else if(fields[i] == Field.C){
initC();
} else if(fields[i] == Field.D){
initD();
} else if(fields[i] == Field.E){
initE();
} ....
}
}
Sounds like your design might need to be looked at. A few suggestions:
Add the init method to your enum. So
then you can iterate around the array
of your enums and call the init
method on it, so the enum knows how
to do its own initialization
create a Command object which does
the initialization and create a
Map of your enum as the key and
the Command as the value. Cycle
round the map running the Command
for each enum.
Use reflection - cost wise I wouldn't be too concerned for this, unless your system is after incredibly low latency
For the first bullet, you could change the TextBox to hold a Field type against it e.g.
TextBox A = new TextBox(Field.A);
TextBox B = new TextBox(Field.B);
So if TextBox knows it is A,B,C,D,E then you just need to loop around your Field[] and when it finds its mathing TextBox run the init code (which can be stored against the specific enum instance). Of course you will need to register all your TextBox instances in a data structure somewhere, as you seem very set against using the very widely used reflection API.
In essence there has to be a link between the Field and the TextBox. Java cannot read your mind and know this without you telling it. Well, at least until Google unveil their telepathy API (and that would probably only be for Go...). This can be done based on naming (reflection), hardcoded logic (ifs or switches) or based on state. For the latter this means associating the Field with the TextBox, as I have demonstrated with the Constructor example above.
From a design perspective I'd choose a combination of Factory pattern, Singleton pattern (enum based) and Command pattern. I see a set of commands where each command is specific for a given value. A factory (Singleton) is a common pattern to create such specialized instances. Even though it simply moves the if/switch chain into the factory (but factories are allowed use conditional checks in order to create the instances..).
// the init command
public interface PanelInitializer {
public init(Panel p);
}
// the factory
public enum PanelInitializerFactory {
INSTANCE;
public PanelInitializer create(Field field) {
switch (field) {
case A: return new TypeAInitializer();
case B: return new TypeBInitializer();
case C: return new TypeCInitializer();
//..
}
}
}
I don't think that we can get rid of all conditional checks without using naming conventions and reflection/instantiation or without introducing the constraint, that all initializers share the same code.
Here's a snippet featuring adding the init method to the enum. In each Field's init method you can call one of your different initX() methods. Making the init method abstract gets the compiler to remind you to define your init method for the enum value.
enum Field
{
A{public void init(){initA();}},
B{public void init(){initB();}},
C{public void init(){initC();}},
public abstract void init();
}
You can, as #planetjones mentioned, add an init() method to your enum class. The init method should return a reference to the initialised TextBox of its (enum) type. If you need to pass data to the initialisor you can pass this so that it can retrieve any information it needs.
To get around the problem of finding the variable to assign to, you can either declare an array of TextBoxes
public void init(){
for(int i = 0 ; i < fields.length; i++){
F[i] = fields[i].init(this);
}
}
or assign them after you initialised a temporary array.
public void init(){
TextBox F[5];
for(int i = 0 ; i < fields.length; i++){
F[i] = fields[i].init(this);
}
A = F[0];
B = F[1];
C = F[2];
D = F[3];
E = F[4];
}
Of course you should declare constants instead of using magic numbers.
You could use java reflection to loop through your enum, but you really should look into some way to consolidate all your initN() methods.
Why you current implementation is bad? Only because it looks "ugly"? You can use switch instead of bunch of if:
public void init(){
for(int i = 0 ; i < fields.length; i++){
switch(fields(i)){
case A:
initA();
break
case B:
...
}
}
}
Maybe logic in initA, initB... is very similar? If you have 20 different enums, and 20 different init to run, not much space for improvement...
You could do it, for example, by moving initialization logic to the enum. Have there a method initialize that takes a TextBox as the parameter and initializes it.
BTW you would be better having the TextBox variables in an array.
EDIT
Another option is, what I often is I use an enum as a sort of archetype storage. There I have a method returning an object which matches a certain enum type.
If you do not want to have initialization in enum you could move it to objects you are going to return. There for each particular object you will have a separate initialization.
I am afraid that you are trying to chase the dragon with this one.
Look at it this way. Since the problem of yours is 'conditional', i.e. you have to do a different initialization depending on enum type of a Field, thus at some point you will have to use ifs or switch statement.
Believe there is no magic way around it, how the program should know what you want to do? Even using reflection you will use ifs, etc. to initialize it accordingly.
Your approach is not at all bad if the init methods associated with each TextBox is very different, and the list of Fields is small. Also, if you typically instantiate only one of these Panel instances, the other approaches can actually hurt more than help.
Having said that, consider using a java.util.EnumMap. After that, you have three choices:
register the TextBoxes in some other array as well,
invoke the initA, ... using reflection or
invoke them using some functor construct.
The best choice depends on use case.
Start with this example:
import java.util.HashMap;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class FooPanelMain {
public static void main(String[] args) {
FooPanel panel = new FooPanel();
JFrame frame = new JFrame();
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
}
class FooPanel extends JPanel {
// fields are dynamically created, so we put them into a map
private Map<PanelField, JLabel> fields = new HashMap<PanelField, JLabel>();
// enum to configure the fields
private enum PanelField {
FIRST("first text"),
SECOND("second text"),
LAST("last text");
private String text;
private PanelField(String text) {
this.text = text;
}
public String getLabelName() {
return text;
}
}
// constructor uses the enum configuration to create the fields
public FooPanel() {
for (PanelField fooPanelField : PanelField.values()) {
createLabel(fooPanelField);
}
}
private void createLabel(PanelField field) {
JLabel label = new JLabel(field.getLabelName());
this.add(label);
fields.put(field, label);
}
}
This example can be easily turned into a abstract solution by defining an interface for PanelField, that is implemented by enums. FooPanel can be used as a base class for Panels.
best u move the init into the enum, just like:
public enum Example{
value1(1),
value2(2),
value3(66);
private final int internalValue;
Example(int value){
this.internalValue = value;
}
public int getInternalValue(){
return this.internalValue;
}
}
Although this is really simple example, you can add any code to the constructor later on and have more complex decisions based on the actual object itself.