I've been searching to many places but I didn't find a good answer for my problem:
I have an enum, for example:
public enum Window { CLASSIC, MODERN }
and I need to separate the behavior of my application according to the enum value, like that:
switch (myWindow.getType()) {
case CLASSIC: new ClassicWindow(...);
case MODERN: new ModernWindow(...);
}
I know what you think: simply put that in the enum and basta, however this is not the only class depending on my enum! And I can't write as many object creation methods as I have objects!
Simply put, what can I do in this situation? A friend of mine said to me to get rid of the enum and to use derived classes everytime, but in the end I'd have to create as many instances as subclasses for all my tests!
In short, I'm stuck.
Do you know a best practice for that? Thanks
You seem to be looking for a design pattern, rather than good practices for using enums. The code you're intending to write will be full of switch statements, with one condition for each possible value of the enum - making it hard to maintain and extend in the long run. A better idea would be to refactor each possible case's behavior in a separate class, maybe using the Abstract Factory pattern.
This is the factory pattern. This example actually shows exactly what you're doing.
You could either implement an interface in your enum and have them act as a factory:
interface WindowBuilder {
Window makeWindow();
}
enum WindowType implements WindowBuilder {
SIMPLE {
public Window makeWindow() { return new SimpleWindow() }
},
[... other enums]
}
or you could use reflection and bind a class to the enum type to have them (again) work as a factory:
enum WindowType {
SIMPLE(SimpleWindow.class),
[... other enums]
private final Class<? extends Window> wndType;
private WindowType(Class<? extends Window> wndType) {
this.wndType = wndType;
}
public Window makeWindow() {
// in fact you will need to either catch the exceptions newInstance can throw, or declare the method can throw them
return this.wndType.newInstance();
}
}
Either way you will be able to call them like that afterward:
Window window = myWindow.getType().makeWindow();
Related
I have a situation where I would like to used an instance of an object called Abstraction, which would be a Java interface looking something like:
public interface Abstraction {
public enum Actions {
}
}
The idea being that any class implementing Abstraction has to implement enum Actions (I realise this doesn't work).
A class implementing the interface may look like:
public class AbstractionA implements Abstraction {
public enum Actions {
f, c, r, a
}
}
In another class I would want to create an Abstraction object like:
Abstraction abs = new AbstractionA();
and then be able to access the enum values applicable to the Abstraction object created, e.g.
abs.Action.r;
I realise my approach to this is all wrong but cannot see an appropriate way to handle this type of situation. How can I implement something like this where different implementations of the interface have a varying subset of the options I would generally want to put in an enum?
Perhaps I can implement the enum with all possible options in the interface and then somehow restrict implementations of the interface to using a subset of those enum values?
EDIT:
Another example implementation might be
public class AbstractionB implements Abstraction {
public enum Actions {
f, c, b, r, a
}
}
I think I have figured out a way forward with this:
public interface Abstraction {
public enum Actions {
f, c, b, r, s, a
}
public Actions[] availableActions();
}
Then implement with:
public class HunlAbstractionA implements Abstraction{
#Override
public Actions[] availableActions()
{
Actions[] actions = new Actions[] {Actions.f, Actions.c, Actions.r, Actions.a};
return actions;
}
}
This way I have access to all possible actions listed in the interfaces enum and can make checks to ensure an Action to be dealt with is one of the availableActions for the created class.
Recommendation
I'd recommend the following approach.
This approach uses a combination of generics and reflection to help explicitly indicate the need to implement or choose an appropriate enum, it also gives you the option of preserving information about the enum type whilst hiding all other information about the specific Abstraction implementation.
/**
* An abstraction with an implementation-defined enum
* #param <E> your custom enum.
*/
interface Abstraction<E extends Enum> {
//this gives you the enum constants as a list
Class<E> getEnumType();
}
class AbstractionA implements Abstraction<AbstractionA.EnumA> {
enum EnumA {
FOO,
BAR
}
#Override
public Class<EnumA> getEnumType() {
return EnumA.class;
}
}
class AbstractionB implements Abstraction<AbstractionB.EnumB> {
enum EnumB {
FOO,
BAR
}
#Override
public Class<EnumB> getEnumType() {
return EnumB.class;
}
}
Note that unfortunately we can supply a default implementation of getEnumType() due to type erasure.
Usage Example
class Main {
public static void main(String[] args) {
Abstraction myAbstractionA = new AbstractionA();
Abstraction<AbstractionB.EnumB> myAbstractionB = new AbstractionB();
Class enumAType = myAbstractionA.getEnumType();
Class<AbstractionB.EnumB> enumBType = myAbstractionB.getEnumType();
Object[] enumsA = enumAType.getEnumConstants();
AbstractionB.EnumB[] enumsB = enumBType.getEnumConstants();
System.out.printf("Enums of the same order are still non-identical: %s", enumsA[0].equals(enumsB[0]));
System.out.println();
Enum enumA = ((Enum)enumsA[0]);
Enum enumB = ((Enum)enumsB[1]);
System.out.printf("We can get enum constants in order, and get the orderinal of the enum: A=%s, B=%s", enumA.ordinal(), enumB.ordinal());
System.out.println();
enumA = Enum.valueOf(enumAType, "FOO");
enumB = Enum.valueOf(enumBType, "BAR");
System.out.printf("We can get enum constants by name and get the name out of the enum: A=%s, B=%s", enumA.name(), enumB.name());
System.out.println();
}
}
Alternatives
If you can use an abstract class instead of an interface, you may prefer a solution similar to this related answer.
Edit: If you have a common set of constants you want to share across your actions, you should probably use a global/shared enum for those constants and define only the extensions themselves in the custom Abstractions. If you cast them all to Enum and use .equals() as needed, this should work in most cases.
Background
As you have stated you know, it is not possible to place member objects (variable or classes) of an interface.
However, the good news is that java actually supports the behaviour you want pretty well.
There are 3 key features that relate to my recommendation:
Enums are Objects
Firstly, enums in java are fully-fledged Objects, which all extend java.lang.Enum, and all implement .equals().
So, you can store different any enum class' values in a variable of type java.lang.Enum and compare them with .equals().
And, if you want to pretend that values of different enum classes are the same because they share the same name (or are the nth constant in their respective class), you can do that too.
Note that this also means that custom enums can contain complex data and behaviour like any other class, beyond it's use as a unique identifier.
See the Enum API documentation for details.
Java Reflection
Secondly, Java has extensive reflection support. For our purposes, java.lang.Class has a method called getEnumConstants() for getting the enum constants (or null if the class is not an enum).
See the Class API documentation for details.
Cyclic Dependancies
Thirdly, at least when it comes to generics, Java is permissive when it comes to cyclic dependancies, so you can define a generic interface depends on a specialisation of that generic. Java won't mind.
Interface is a contract that you want anyone to provide an implementation of that contract. In your example code you do not have a method but a definition of a enum called Action.
Generally enum is a set of constants hence we do not expect multiple classes to come up with different implementations of the same constant.
So you might want to rethink about your approach and figure out a better way. Hope this will help moving you in correct direction.
I am implementing the factory pattern in my code, so came across one interesting thing in factory that I can replace the if else condition in the factory method with Reflection to make my code more dynamic.
Below is the code for both the designs......
1) With if-else conditions
public static Pizza createPizza(String type) {
Pizza pizza = null;
if(type.equals(PizzaType.Cheese))
{
pizza = new CheesePizza();
}
else if (type.equals(PizzaType.Tomato))
{
pizza = new TomatoPizza();
}
else if (type.equals(PizzaType.Capsicum))
{
pizza = new CapsicumPizza();
}
else
{
try {
throw new Exception("Entered PizzaType is not Valid");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return pizza;
}
2) With Reflection
public static Pizza createPizza(String type) {
Pizza pizza = null;
for(PizzaType value : PizzaType.values())
{
if(type.equals(value.getPizzaTypeValue()))
{
String fullyQualifiedclassname = value.getClassNameByPizzaType(type);
try {
pizza = (Pizza)Class.forName(fullyQualifiedclassname).newInstance();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return pizza;
}
Second way looks very good to me as I can make my code more dynamic by using it, as I can create one property file with the names of classes and type associated with it to serve the Open and close a bit more, as if in future owners wants to add more pizzas to PizzaStore then he would just make the entry in the property file and will just create one more subclass of Pizza.
But I read that reflection has many disadvantages mentioned few of them.
It is hack of compiler
Automatic development tools are not able to work with reflections code
It's difficult to debug reflections code
Reflection complicates understanding and navigation in code
Significant performance penalty
So very curious to know that, which design is good, as I am very interested to make my code more and more dynamic.
You can also use a design in the middle. E.g.
public interface Factory<T> {
public T newInstance();
}
public class TomatoPizzaFactory implements Factory<TomatoPizza> {
#Override
public TomatoPizza newInstance() {
return new TomatoPizza();
}
}
public class PizzaFactory {
private Map<String, Factory<? extends Pizza>> factories = new HashMap<String, Factory<? extends Pizza>>();
public PizzaFactory(){
factories.put(PizzaType.Cheese, new CheesePizzaFactory());
factories.put(PizzaType.Tomato, new TomatoPizzaFactory());
}
public Pizza createPizza(String type){
Factory<? extends Pizza> factory = factories.get(type);
if(factory == null){
throw new IllegalArgumentException("Unknown pizza type");
}
return factory.newInstance();
}
}
Implement a DefaultConstructorFactory for simple instantiations.
public class DefaultConstructorFactory<T> implements Factory<T> {
private Class<T> type;
public DefaultConstructorFactory(Class<T> type) {
this.type = type;
}
public T newInstance() {
try {
return type.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("Can not instantiate " + type, e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Can not instantiate " + type, e);
}
}
}
But I read that reflection has many disadvantages mentioned few of them.
It is hack of compiler
It can be a hack, but if you are writing infrastructure code you will often use reflections. Especially when you write frameworks that must introspect classes at runtime, because the framework doesn't know the classes it will handle at runtime. Think about hibernate, spring, jpa, etc.
Automatic development tools are not able to work with reflections code
That's true, because you shift a lot of compiler issues to runtime. So you should handle reflection exceptions like a compiler and provide good error messages.
There is also only a little refactoring support in some IDEs. So you must be careful when changing code used by reflection code.
Nevertheless you can write tests to find bugs fast.
It's difficult to debug reflections code
That's also true, because you can't jump into a method directly and you have to investigate the variables to find out which member of which object is accessed.
It is a bit more indirection.
Reflection complicates understanding and navigation in code
Yes, if it is used the wrong way. Only use reflection if you do not know the types you have to handle at runtime (infrastructure or framework code). Don't use reflection if you know the types and you only want to minimize code written. If you want to minimize code written select a better design.
Significant performance penalty
I don't think so. Of course reflection calls are indirect method invokations and thus more code must be executed in order to do the same as a direct method call. But the overhead for this is minimal.
If you use reflection code in factories, the reflection overhead is insignificant compared to the lifetime of the created objects.
Also your reflection code will be JIT optimized. Since Java 1.4 the hot spot compiler will inflate a method that is reflectively called more then 15 times by generating a pure-java accessor.
See:https://blogs.oracle.com/buck/entry/inflation_system_properties, https://stackoverflow.com/a/7809300/974186 and https://stackoverflow.com/a/28809546/974186
Frameworks use reflection and generate a lot of proxies that use reflection, e.g. spring's transaction management, jpa, etc. If it would have a significant performance impact all applications using these frameworks would be very slow, wouldn't they.
Using reflection this way is not recommended in general,
but if creating objects dynamically is a top priority in your design,
then it can be acceptable.
Another good option might be to not use different Pizza subtypes,
but a single Pizza class that can be parameterized.
That would make a lot of sense,
since I don't think pizzas behave so very differently.
It seems to me that a diverse range of pizzas could be easily created using the builder pattern.
Btw, another bad practices catches the eye here,
that the parameter of the factory method is a String,
when you actually seem to have PizzaType which is an enum,
and you compare the String parameter to enum values.
It would be much better to use enum values as the parameter,
and a switch instead of the chained if-else.
But, another problem here is that the enum duplicates the available pizza types. So when you add a new pizza type, you also have to update the enum, and the factory method. That's too many files changed. This is code smell.
I suggest to give a try to the single Pizza class and the builder pattern.
Reflection seems like an overkill to me in this situation. Why don't you add a factory method Pizza create(); to your PizzaType interface?
Then just make every implementing class do the initialization, like:
class CheesePizza implements PizzaType {
Pizza create() {
return new CheesePizza();
}
}
So you only end up with:
for(PizzaType value : PizzaType.values()
if(type.equals(value))
pizza = value.create();
This way the loop in the first example wouldn't be ineffective and it is expandable easily .
Also you shouldn't worry about reflection performance too much, if your code hasn't a need to perform in realtime. I agree, that it makes the code unreadable though, so avoiding it is better in most cases.
Edit: I've overseen, that PizzaType is an enum, not an Interface. In this case you may create one or add a create method to your enum, but I don't think the latter is very favourable.
The if - else statements won't contribute to your design. This merely ensures that the pizza's exist - in a inheritance hierarchy. Try to use a decorator pattern to minimise the hierarchy levels and use a concrete class (like: plainPizza) to add your decorations to.
The decorator pattern is aimed at adding decorations dynamically in run-time.
If you have only few classes returned by factory (let's say three or four) you should just leave it in simplest form with if statements
if(type.equals("someType"){
return new SomeType();
} else if(type.equals("otherType"){
return new OtherType();
}
If you have more class types or you predict frequent changes in this hierarchy then you should switch to implementation where factory class will have collection of available implementations. Your factory class will have field with possible instance types.
public class MyFactory{
private Map<String, Class<? extends ReturnedClass> availableTypes;
}
It might be problematic how to fill this map with elements.
You may:
Hardcode them inside constructor/ init method inside Factory. Note: each new added class will require changes in factory.
Make method registerNewReturnedType(Class c) inside factory. Each returned class will have to register itself inside factory. Note: after adding new class you will not have to change factory
(Recommended) Use dependency injection to fill map.
I want to create a private Interface in Class A and have it implemented by Class B. My intention is to have a way for Class A to call a method set on class B that NO ONE else can call. They are in separate file in separate packages. Anyone have any ideas?
The best you can achieve is to give the interface package level visibility and move Class A and B into the same package.
This doesn't stop someone adding another class into the same package in the future, thus giving it access to the interface.
short answer is redesign your class structure.
But if you really need to, consider to use reflex feature in java. and you can inject the method although not recommended.
Disclaimer: not a Java programmer.
But if you want to leverage a type system to get compile-time errors... there are often tricks by introducing a new data type as a sort of "access token" or "dummy parameter". Make it hard to get ahold of a value of that type, but require a value of that type as a parameter in the interface.
Yet introducing a hoop like that winds up being about as contrived as renaming your methods alarming things like DoFooActionOnClassB_ButDontCallUnlessYouAreClassA. I think one usually finds that in a good design, this "dummy type" isn't a dummy type at all... but a capture of the context and state that you should have had in the first place.
I understand that you want to have methods on class B which can only be called from class A. One way would be deferring the real check until runtime but let the compiler make it hard to do the wrong thing. So you could try using a secret which only class A can have in order to protect the method in class B.
public class A {
private static final PrivateA PROOF = new PrivateA();
public static class PrivateA {
private PrivateA() { }
// only A can extend PrivateA
}
public static void main(String[] args) {
new B().methodForAOnly(PROOF, "A");
}
}
Here A's PrivateA is a type which only A can instantiate or extend, and B knows about that...
public class B {
public void methodForAOnly(PrivateA proof, String param) {
if (proof == null) throw new NullPointerException();
// do something
System.out.println(param);
}
}
Recently, I've discovered this code of the following structure:
Interface:
public interface Base<T> {
public T fromValue(String v);
}
Enum implementation:
public enum AddressType implements Base<AddressType> {
NotSpecified("Not Specified."),
Physical("Physical"),
Postal("Postal");
private final String label;
private AddressType(String label) {
this.label = label;
}
public String getLabel() {
return this.label;
}
#Override
public AddressType fromValue(String v) {
return valueOf(v);
}
}
My immediate reaction is that one cannot create an instance of an enum by deserialization or by reflection, so the fromValue() should be static.
I'm not trying to start a debate, but is this correct? I have read, Why would an Enum implement an interface, and I totally agree with the answers provided, but the above example is invalid.
I am doing this because the "architect" doesn't want to take my answer, so this is to create a strong argument (with facts) why the above approach is good/bad.
Your Base interface does not declare valueOf and the fromValue method is indeed implemented. I see no reason why this code should not compile. If you are referring to the valueOf call inside fromValue, that is a call of a static method defined for every enum. I would have to agree, though, that the design of it is quite misguided as you need an arbitrary member of the enum just to call fromValue and get the real member.
On the other hand, in a project that I'm doing right now I have several enums implementing a common interface. This because the enums are related and I want to be able to treat them uniformly with respect to their common semantics.
In my opinion this design is wrong. In order to use valueFrom() one has to get an instance of this enum beforehand. Thus, it will look like:
AddressType type = AddressType.Postal.valueFrom("Physical");
What sense does it make?
Your Base interface seems to serve a whole other purpose (if any).
It is probably meant to be a String-to-T-converter, since it generates a T from a String. The enum is simply wrong if it implements this interface (#yegor256 already pointed out why). So you can keep the enum and you can have some AddressTypeConverter implements Base<AddressType> which calls AddressType.valueOf() in its fromString() method.
But don't get me wrong: enums implementing interfaces are NOT a bad practice, it's just this particular usage that is completely wrong.
We've got a set of classes which derive from a common set of interfaces such that
IFoo-> BasicFoo, ReverseFoo, ForwardFoo
IBar -> UpBar, DownBar, SidewaysBar
IYelp -> Yip, Yap, Yup
wherein the constructor for the Foo's looks like Foo(IBar, IYelp) These items are used throughout the project.
There exists another class which has a method whose signature is public double CalcSomething(IFoo, IAnotherClass) that is applied at some point to each and every Foo. We've had a request come down from above that one particular object composition, let's say a BasicFoo(UpBar,Yip), use a different algorithm other than the one found in CalcSomething.
My first instinct was to say let's change the IFoo interface so we can move the logic down to the Foo class level, change the constructor to be Foo(IBar, IYelp, IStrategy) and then have the Foo objects encapsulate this logic. Unfortunately we've also been told the design of the architecture stipulates that there be no dependencies between IFoo, it's implementations and IAnotherClass. They're adamant about this.
Ok, sure, then I thought I might use a visitor pattern but... how? The whole point of making the composition was so that no other class could see the implementation details. Reflection to look inside the objects, totally breaking encapsulation? Oh hell no.
So I've come here because I'm at a loss. Does anyone have any suggestions how we could treat a special case of one of the compositions without modifying the composition or breaking encapsulation? There has got to be a simple solution I'm over-looking.
Edit:
Removed offending beginning.
Changed "handled specially" into a more descriptive meaning.
A CalculationFactory that chooses an appropriate algorithm based on the type of IFoo you provide would solve the problem (at the cost of a conditional):
interface ICalcSomethingStrategy {
public double CalcSomething(IFoo, IAnotherClass);
}
CalcSomethingStrategyFactory {
ICalcSomethingStrategy CreateCalcSomethingStrategy(IFoo foo) {
// I'm not sure whether this is the idiomatic java way to check types D:
if (foo.Bar instanceof UpBar && foo instanceof Yip) {
return new UnusualCalcSomethingStrategy();
} else {
return new StandardCalcSomethingStrategy();
}
}
}
In the spirit of KISS I would add a method isSpecial() to IFoo, and use that to decide which algorithm to use in CalcSomething().
This assumes that this is the only special case.
There's no way for calcSomething to avoid having the knowledge needed to do the "special" behavior, but other than that, you can maintain most of your encapsulation this way.
Create a marker interface IQualifyForSpecialTreatment which extends IFoo. Extend BasicFoo to SpecialBasicFoo, and have it implement IQualifyForSpecialTreatment.
interface IQualifyForSpecialTreatment extends IFoo {
}
class SpecialBasicFoo extends BasicFoo implements IQualifyForSpecialTreatment {
...
}
You can then add another flavor of calcSomething:
calcSomething (IQualifyForSpecialTreatment foo, IAnotherClass whatever) {
... perform "special" variant of calculation
}
calcSomething (IFoo foo, IAnotherClass whatever) {
... perform "normal" variant of calculation
}