I'm working on a client that uses a standardised web service, however one of the vendors behaves in a slightly different way such that we must take account of these behaviours. To do this we have been using an enum:
public enum ServiceProviderType {
FOO, BAR;
public ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com")) {
return ServiceProviderType.FOO;
} else {
return ServiceProviderType.BAR;
}
}
}
The difference in these behaviours also differ according to what we request from the service, eg we might request a layer and want that layer coloured red, but know that BAR and FOO services represent RGB values differently. To do this we've created another enum that stores the properties we want for each layer in the service.
public enum LayerServiceProviderType {
FOO("#ff0000"),
BAR("#ff5555");
private String colour;
public ServiceProviderType(String colour) {
this.colour = colour;
}
public String getColour() {
return colour;
}
public ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com")) {
return ServiceProviderType.FOO
} else {
return ServiceProviderType.BAR;
}
}
}
This works fine except for when we want to handle multiple layers and treat them as all being derivative of the same base enum. Essentially we want to handle Layer1ServiceProviderType.BAR as being equivalent to Layer2ServiceProviderType.BAR. But we can't subclass enums, and even attempting to do so seems to break all kinds of sound design principles.
My first thought was to have an interface which contains an enum:
interface ServiceProvider {
ServiceProviderType {FOO, BAR};
ServiceProviderType getServiceProviderType();
ServiceProvider checkService(String url);
}
public enum LayerServiceProvider implements ServiceProvider {
FOO (ServiceProviderType.FOO, "#ff0000"),
BAR (ServiceProviderType.BAR, "#ff0000");
public LayerServiceProvider(ServiceProviderType serviceProviderType, String colour) {
this.serviceProviderType = serviceProviderType;
this.colour = colour;
}
#Override
public ServiceProviderType getServiceProviderType() {
return this.serviceProviderType;
}
#Override
public ServiceProvider checkService(String url) {
if (url.equals("http://www.example.com")) {
return LayerServiceProviderType.FOO
} else {
return LayerServiceProviderType.BAR;
}
}
}
But it seems overwrought to me to have an enum with in an enum that each hold the same range of values. Is there a better way to do this?
Maybe the Visitor Pattern is what you're looking for.
Used with an enum, it basically allows adding enum-dependent logic without using switch statements.
Example:
public enum ServiceProviderType {
FOO {
#Override public <T> T apply(Action<T> action) { return action.doFoo(); }
},
BAR {
#Override public <T> T apply(Action<T> action) { return action.doBar(); }
};
public interface Action<T> {
T doFoo();
T doBar();
}
public abstract <T> T apply(Action<T> action);
public static ServiceProviderType checkService(String url) {
if (url.equals("http://www.example.com"))
return FOO;
return BAR;
}
}
public class LayerServiceProviderType implements ServiceProviderType.Action<String> {
#Override
public String doFoo() {
return "#ff0000";
}
#Override
public String doBar() {
return "#ff0000";
}
}
public class Main {
public static void main(String[] args) {
ServiceProviderType type = ServiceProviderType.checkService("");
String colour = type.apply(new LayerServiceProviderType());
}
}
Related
Small question regarding the diamond operator and design pattern strategy for Java, please.
I would like to implement a very specific requirement:
there are some objects to store (in my example called MyThingToStore)
and the requirement is to store them with different kinds of data structures, for comparison.
Therefore, I went to try with a strategy pattern, where each of the strategies is a different way to store, I think this pattern is quite lovely.
The code is as follows:
public class MyThingToStore {
private final String name;
public MyThingToStore(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyThingToStore that = (MyThingToStore) o;
return Objects.equals(name, that.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "MyThingToStore{" +
"name='" + name + '\'' +
'}';
}
}
public class MyStorage {
private final StorageStrategy storageStrategy;
public MyStorage(StorageStrategy storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
public interface StorageStrategy {
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy{
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And this is working fine, very happy, especially tackled the requirement "easy to change the data structure to do the actual store".
(By the way, side question, if there is an even better way to do this, please let me know!)
Now, looking online at different implementations of strategy patterns, I see this diamond operator which I am having a hard time understanding:
MyThingToStore stays the same.
public class MyStorage {
private final StorageStrategy<MyThingToStore> storageStrategy; //note the diamond here
public MyStorage(StorageStrategy<MyThingToStore> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
#Override
public String toString() {
return "MyStorage{" +
"storageStrategy=" + storageStrategy +
'}';
}
}
public interface StorageStrategy<MyThingToStore> {
//note the diamond, and it will be colored differently in IDEs
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy<MyThingToStore> {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy<MyThingToStore> {
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy<MyThingToStore> storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And both versions will yield the same good result, also be able to answer requirements.
My question is: what are the differences between the version without a diamond operator, and the version with the diamond operator, please?
Which of the two ways are "better" and why?
While this question might appear to be "too vague", I believe there is a reason for a better choice.
I think the confusion comes from how you named type parameter for StorageStrategy in your 2nd example.
Let's name it T for type instead. T in this case is just a placeholder to express what type of objects your StorageStrategy can work with.
public interface StorageStrategy<T> {
void addToStore(T myThingToStore);
int getSize();
}
E.g.
StorageStrategy<MyThingToStore> strategy1 = // Initialization
StorageStrategy<String> strategy2 = // Initialization
strategy1.addToStore(new MyThingToStore("Apple"));
// This works fine, because strategy2 accepts "String" instead of "MyThingToStore"
strategy2.addToStore("Apple");
// Last line doesn't work, because strategy1 can only handle objects of type "MyThingToStore"
strategy1.addToStore("Apple");
To make it work properly, you need to change your different StorageStrategy implementations to also include the type parameter.
public class StorageUsingHashSetStrategy<T> implements StorageStrategy<T> {
private final Set<T> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(T myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
And lastly you also want to have a type paremeter for MyStorage
public class MyStorage<T> {
private final StorageStrategy<T> storageStrategy;
public MyStorage(StorageStrategy<T> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(T myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
Now you can create a MyStorage and can use it to store essentially any object into it and not just MyThingToStore. Whether that is something you want or not is up to you.
In the second code sample in the declaration of the interface StorageStrategy<MyThingToStore>, MyThingToStore is a Type Variable.
I.e. it's not the actual type, only a placeholder for a type, like T. The common convention is to use single-letter generic type variables (T, U, R, etc.), otherwise it might look confusing like in this case.
Note that in the class declarations, like:
public class StorageUsingArrayListStrategy
implements StorageStrategy<MyThingToStore>
MyThingToStore is no longer a type variable, but the name of the class MyThingToStore because in this case parameterized interface is implemented by a non-parameterized class (i.e. the actual type known to the compile is expected to be provided).
I am looking for some help in designing the factory of concrete implementations of a generic interface. Java version 7, can not use 8+
Given such interface and abstract class:
public interface ValidationStrategy<T> {
String getNativeQuery();
ValidationStrategy<T> withValue(T value);
}
public abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
protected T value;
public void setValue(T value) {
this.value = value;
}
}
I want to have multiple implementations of such interface like:
public class DocumentValidationStrategy extends AbstractValidationStrategy<String> {
#Override
public String getNativeQuery() {
// here goes customer native query
return null;
}
#Override
public ValidationStrategy<String> withValue(String value) {
setValue(value);
return this;
}
}
The ValidationStrategy would be decided upon predefined enum (interface, has to be cross-platform unified) by the, ideally, a factory. The problems are generics and I can not really go around them with nor I haven't crossed any question that would address my problem
public class ValidationStrategyFactory {
private static final Map<CustomerValueValidationEnum, Class<? extends ValidationStrategy<?>>> validationStrategiesMap = new HashMap<>();
{
validationStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT, DocumentValidationStrategy.class);
}
private static Class<? extends ValidationStrategy<?>> getInstance(CustomerValueValidationEnum validationEnum) {
return validationStrategiesMap.get(validationEnum);
}
public static ValidationStrategy<?> createInstance(CustomerValueValidationEnum validationEnum)
throws IllegalAccessException, InstantiationException {
return getInstance(validationEnum).newInstance();
}
}
This obviously leads to problems where I can not create the proper implemntation of the ValidationStrategy interface due to my bad usage of java generics where I try to:
public boolean isValueUnique(CustomerValueValidationEnum type, Object value) {
try {
ValidationStrategyFactory.createInstance(type).withValue(value);
} catch (IllegalAccessException | InstantiationException e) {
throw new UnsupportedOperationException();
}
return false;
}
which obviously does not work as I can not feed value the way I want (value can be everything, a String, Integer or a List). I know that I am trying to combine factory and strategy patterns and I tried my best to combine both of them, I guess it is a bad pattern but now I do not really know how else can I create easily extensible validation mechanism that would only require me to create a single class.
EDIT: as requested, simple enum class that is shared between multiple services and it should not contain any business logic.
public enum CustomerValueValidationEnum {
VALIDATE_DOCUMENT("validateDocumentNumber")
;
private final String name;
private CustomerValueValidationEnum(String name) {
this.name = name;
}
#ValueMapKey
public String getName() {
return this.name;
}
}
It is impossible to type dynamically any generic type as it's checked during compilation. I suggest you to make your factory switch on your enum (using/or not a Map).
Implementation without Map :
enum CustomerValueValidationEnum { // Not provided by OP
VALIDATE_DOCUMENT,
VALIDATE_NUMBER
}
interface ValidationStrategy<T> {
String getNativeQuery();
ValidationStrategy<T> withValue(T value);
}
abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
protected T value;
public void setValue(T value) {
this.value = value;
}
#Override
public String getNativeQuery() {
return null;
}
#Override
public ValidationStrategy<T> withValue(T value) {
setValue(value);
return this;
}
}
class DocumentValidationStrategy<T> extends AbstractValidationStrategy<T> {
#Override
public String getNativeQuery() {
return "Customer Query";
}
}
class ValidationStrategyFactory {
// Generic types are checked during compilation time, can't type it dynamically
public static ValidationStrategy<?> createInstance(CustomerValueValidationEnum validationEnum) {
ValidationStrategy valStrat = null;
switch(validationEnum) {
case VALIDATE_DOCUMENT:
valStrat = new DocumentValidationStrategy<String>();
case VALIDATE_NUMBER:
valStrat = new DocumentValidationStrategy<Integer>();
}
return valStrat;
}
}
Implementation with Map :
import java.util.HashMap;
import java.util.Map;
enum CustomerValueValidationEnum { // Not provided by OP
VALIDATE_DOCUMENT(String.class),
VALIDATE_NUMBER(Integer.class);
private Class validationType;
CustomerValueValidationEnum(Class cls) {
validationType = cls;
}
public Class getValidationType() {
return validationType;
}
}
interface ValidationStrategy<T> {
String getNativeQuery();
ValidationStrategy<T> withValue(T value);
}
abstract class AbstractValidationStrategy<T> implements ValidationStrategy<T> {
protected T value;
public void setValue(T value) {
this.value = value;
}
#Override
public String getNativeQuery() {
return null;
}
#Override
public ValidationStrategy<T> withValue(T value) {
setValue(value);
return this;
}
}
class DocumentValidationStrategy<T> extends AbstractValidationStrategy<T> {
#Override
public String getNativeQuery() {
return "Customer Query";
}
}
class ValidationStrategyFactory {
private static final Map<Class, ValidationStrategy> validationStrategiesMap = new HashMap<>();
{
validationStrategiesMap.put(String.class, new DocumentValidationStrategy<String>());
validationStrategiesMap.put(Integer.class, new DocumentValidationStrategy<Integer>());
}
private static ValidationStrategy<?> getInstance(CustomerValueValidationEnum validationEnum) {
return validationStrategiesMap.get(validationEnum.getValidationType());
}
}
You can't use generic type through enum (without implementing an interface) : Post
You can't type dynamically any generic type : Post
One workaround is using a way to get each generic type strategy with a separate method getting from a separate map.
The lower number of various strategy generic types, the more appropriate this way is.
public class StrategyFactory {
static final Map<CustomerValueValidationEnum, ValidationStrategy<String>> validationStringStrategiesMap = new HashMap<>() {{
validationStringStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT_STRING, new DocumentStringValidationStrategy());
}};
static final Map<CustomerValueValidationEnum, ValidationStrategy<Integer>> validationIntegerStrategiesMap = new HashMap<>() {{
validationIntegerStrategiesMap.put(CustomerValueValidationEnum.VALIDATE_DOCUMENT_INTEGER, new DocumentIntegerValidationStrategy());
}};
public static ValidationStrategy<String> stringStrategy(CustomerValueValidationEnum e) {
return validationStringStrategiesMap.get(e);
}
public static ValidationStrategy<Integer> integerStrategy(CustomerValueValidationEnum e) {
return validationIntegerStrategiesMap.get(e);
}
}
public class DocumentStringValidationStrategy extends AbstractValidationStrategy<String> { ... }
public class DocumentIntegerValidationStrategy extends AbstractValidationStrategy<Integer> { ... }
Advantages:
The generic type will be always inferred: StrategyFactory.integerStrategy(null).withValue(1); which means the user-call is very comfortable.
Scales with a low number of generic types: 2 generic type of strategies -> 2 maps -> 2 methods.
Disadvantage:
The user must know if the String-type or Integer-type is to be requested.
Doesn't scale with a high number of generic types: if each strategy has a custom type, then this solution will not help you at all.
Characteristics:
Not null-safe, the map can return null (I'd use null-object pattern for safe behavior). This would be issue even in any of your solutions
I try create Payment by strategy pattern. But All articles each I read look like this:
public interface PayStrategy {
void pay(BigDecimal paymentAmount);
}
But if I need return Single<RestResponse<PaymentResponse>>?Is this the right approach?
public interface PayStrategy {
Single<RestResponse<PaymentResponse>> pay(BigDecimal paymentAmount);
}
In any real system, the request for payment will return the result
I will suggest you to implement your problem statement in Generic return type like below:
public interface IPayStrategy<T> {
T Pay();
}
public class PayStrategy1 :IPayStrategy<int> {
public int Pay() { }
}
public class PayStrategy2 :IPayStrategy<String> {
public String Pay() { .. }
}
public class Context<T> {
private IPayStrategy<T> payStrategy;
public setStrategy(IPayStrategy<T> strategy) { this.payStrategy = strategy; }
public T doPayment() {
return payStrategy.Pay();
}
}
in my opinion it's right because it's up to you the definition of the contract, if you agree that all the strategies must return a result that is of type Single<RestResponse<PaymentResponse>> for me it's correct
I have a requirement that is close to extending enums and since that is not possible, after doing some research online, I came up with this approach of using interfaces and making the enums extend them.
My problem is that I have a few basic types A,B and a flag for each type that says if that has to be checked. Similarly I have some extended types C... which do the same stuff after checking their flags.
Here is the code that does this
Type Interface:
public interface Type {
public String name();
}
Here is the class that uses the basic types
public class BasicChecker {
private static boolean checkA = false;
private static boolean checkB = false;
public enum BasicType implements Type {
A, B;
}
public static boolean isCheckA() {
return checkA;
}
public static void setCheckA(boolean checkA) {
BasicChecker.checkA = checkA;
}
public static boolean isCheckB() {
return checkB;
}
public static void setCheckB(boolean checkB) {
BasicChecker.checkB = checkB;
}
public static void doStuff(String message, Type type) {
if (type.name().equalsIgnoreCase(BasicType.A.name())) {
doStuff(message, isCheckA());
} else if (type.name().equalsIgnoreCase(BasicType.B.name())) {
doStuff(message, isCheckB());
}
}
protected static void doStuff(String message, boolean flag) {
if (someCheckMethod() && flag) {
doStuff(message, flag);
}
}
private static boolean someCheckMethod() {
return false;
}
}
And this is the class that uses extended types
public class ExtendedChecker extends BasicChecker {
private static boolean checkC = false;
public enum ExtendedType implements Type {
C;
}
public static boolean isCheckC() {
return checkC;
}
public static void setCheckC(boolean checkC) {
ExtendedChecker.checkC = checkC;
}
public static void doStuff(String message, Type type) {
BasicChecker.doStuff(message, type);
if (type.name().equalsIgnoreCase(ExtendedType.C.name())) {
doStuff(message, isCheckC());
}
}
}
What I am trying to solve now is to remove all the if else cases from log method. I am also trying to see if there is a better way to do this. Please ignore the statics. I do want them to be static fields and methods.
I'm having trouble understanding exactly what you're trying to do from your description, but you may find abstract methods in enums to be useful.
For example, you could add an abstract method "foo" to your enums:
public enum BasicType implements Type {
A {
public void foo(String message) {
// Do special A stuff
}
}, B {
public void foo(String message) {
// Do special B stuff
}
};
public abstract void foo(String message);
}
And you could then use that method like this:
public static void doStuff(String message, Type type) {
type.foo(message);
}
Naturally, you could put any such abstract methods in an interface you extend, if that's useful.
public class BasicChecker {
private static final Set<Type> _doCheck = Collections.newSetFromMap(new ConcurrentHashMap<Type,Boolean>());
public enum BasicType implements Type {
A, B;
}
public static boolean isCheck(Type type) {
return return _doCheck.contains(type);
}
public static void setCheck(Type type, boolean check) {
if(check) {
_doCheck.add(type);
} else {
_doCheck.remove(type);
}
}
public static void doStuff(String message, Type type) {
doStuff(message, isCheck(type));
}
}
I have two enums describing two UML profiles (meaning they define stereotypes that the profiles contain).
I also have two utility classes featuring nearly identical methods working on each of the profiles.
Example:
public static List<Element> getStereotypedElements(final InsertProfileHere stereo, final Package pkg) {
List<Element> extendedElements = new ArrayList<Element>();
if (isProfileApplied(pkg)) {
if (hasStereotype(stereo, pkg)) {
extendedElements.add(pkg);
}
extendedElements.addAll(getStereotypedElements(stereo, pkg.allOwnedElements()));
}
return extendedElements;
}
,where InsertProfileHere can be replaced with each of the two profile enums.
If anyone is interested, this method uses the Eclipse Modeling Framework or rather the UML2 metamodel implementation in EMF.
Anyway, I want to merge the two utility classes to avoid redundant code.
I've tried:
a super interface for the two profiles
didn't work because of static methods
an abstract class for the Utility classes
didn't work because of static methods
encapsulating the profile enums in a class
Each didn't work for one or another reason.
Anyone got any ideas?
EDIT:
An example for another utility method:
public static boolean hasStereotype(
final InsertProfileHere stereo, final Element elem) {
for (Stereotype appliedStereo : elem.getAppliedStereotypes()) {
if (stereo == null) {
if (InsertProfileHere.contains(appliedStereo)) {
return true;
}
} else if (stereo.isEqual(appliedStereo)) {
return true;
}
}
return false;
}
EDIT2: And for good measure part of the implementation of the profile enum
public enum Profile1 {
STEREOTYPE1 ("readable stereotype1 name"),
STEREOTYPE2 ("readable stereotype2 name"),
STEREOTYPE3 ("readable stereotype3 name"),
public static final String PROFILE_NAME = "NameOfProfile";
private final String readableName;
private Profile1(final String newName) {
readableName = newName;
}
public static Profile1 getValue(final String name) {
for (Profile1 type : Profile1.values()) {
if (type.toString().equals(name)) {
return type;
}
}
return null;
}
public static boolean contains(Stereotype stereotype) {
return (stereotype.getProfile().
getDefinition().getNsURI().contains(PROFILE_NAME));
}
Let the two enums implement a common interface, and use this interface in the (now unified) utility class. Or, better yet, move the methods from the utility class to the interface.
interface Stereotype {
public boolean hasStereotype(Package pkg);
public List<Element> getStereotypedElementes(Package pkg);
}
enum Enum1 implements Stereotype {
FOO("com.foo"), BAR("com.bar");
Enum1(String packagename) {
this.packagename=packagename;
}
private String packagename;
#Override
public boolean hasStereotype(Package pkg) {
return pkg.getName().equals(packagename);
}
#Override
public List<Element> getStereotypedElementes(Package pkg) {
...
}
}
enum Enum2 implements Stereotype {
...
}
public class Foo {
static List<Element> getStereotypedElements(final Stereotype stereo, final Package pkg) {
List<Element> extendedElements = new ArrayList<Element>();
if (isProfileApplied(pkg)) {
if (stereo.hasStereotype(pkg)) {
extendedElements.add(pkg);
}
extendedElements.addAll(stereo.getStereotypedElements(pkg.allOwnedElements()));
}
return extendedElements;
}
}
Use common interface as in example below.
import java.awt.Color;
public class EnumeInteraceTest
{
public interface ICorolsEnum
{
public Color getColor();
}
public enum Colors1 implements ICorolsEnum
{
MAGENTA(Color.MAGENTA),
PINK(Color.PINK);
private Color color;
private Colors1(Color color)
{
this.color = color;
}
#Override
public Color getColor()
{
return color;
}
}
public enum Colors2 implements ICorolsEnum
{
GREEN(Color.GREEN),
BLUE(Color.BLUE);
private Color color;
private Colors2(Color color)
{
this.color = color;
}
#Override
public Color getColor()
{
return color;
}
}
public static void main(String[] args)
{
ICorolsEnum ice1 = Colors1.MAGENTA;
System.out.println(ice1.getColor());
ICorolsEnum ice2 = Colors2.GREEN;
System.out.println(ice2.getColor());
}
}