I want to check if all the ingredients(toppings and fillings) inside a wrap are both vegan and nut free. This is the solution that I came up with, howver I think its a bit inefficient as there is duplication of code. Is there a more efficient way to do it?
(I have a map for all the toppings and fillings which every one contains boolean to know if the topping/filling is vegan and if it is nut free.
public boolean isVegan() {
for (Topping t : toppings) {
if (!t.isVegan()) {
return false;
}
}
for (Filling f : fillings) {
if (!f.isVegan()) {
return false;
}
}
return bread.isVegan();
}
public boolean isNutFree() {
for (Topping t : toppings) {
if (!t.isNutFree()) {
return false;
}
}
for (Filling f : fillings) {
if (!f.isNutFree()) {
return false;
}
}
return bread.isNutFree();
}
Supposing that Ingredient is the base class of these different classes and that this class defines the isVegan() method, you could create a Stream from all these objects and computing whether all are vegan :
public boolean isVegan() {
return
Stream.concat(toppings.stream(), fillings.stream(), Stream.of(bread))
.allMatch(Ingredient::isVegan);
}
For isNutFree() the idea is the same :
public boolean isNutFree() {
return
Stream.concat(toppings.stream(), fillings.stream(), Stream.of(bread))
.allMatch(Ingredient::isNutFree);
}
Note that you could also generalize a matching method to reduce further the duplication :
public boolean allMatch(Predicate<Ingredient> predicate) {
return
Stream.concat(toppings.stream(), fillings.stream(), Stream.of(bread))
.allMatch( i -> predicate.test(i));
}
And use it such as :
boolean isNutFree = allMatch(Ingredient::isNutFree);
boolean isVegan = allMatch(Ingredient::isVegan);
Here is a food type replacing either Topping or Filling or anything:
public interface FoodPart {
boolean isVegan();
boolean isNutFree();
}
Here we have an abstract Food class containing all common codes:
public abstract class Food {
private List<? extends FoodPart> foodParts;
public boolean isVegan() {
return foodParts.stream().noneMatch(foodPart -> foodPart.isVegan());
}
public boolean isNutFree() {
return foodParts.stream().noneMatch(foodPart -> foodPart.isNutFree());
}
}
And here is a concrete and not abstract food:
public class Lasagne extends Food {}
Edit:
If you don't want to inherit from FoodPart then you can change List<? extends FoodPart> simply to List<FoodPart>.
You can also make Food to not abstract so you can easily use it, and don't forget to add getters/setters to provide the foodParts.
Yeez, you guys are fast :)
What I wrote is pretty much already covered in the other answers here but just posting since mine does have some subtle differences (not necessarily better). And since I already went through the motions of writing the code I might as well post it :)
First an interface for your fillings and toppings:
public interface FoodInformation {
boolean isVegan();
boolean isNutFree();
boolean isGlutenFree();
}
Then an abstract class which your toppings and fillings can extend:
public abstract class Ingredient implements FoodInformation {
private boolean vegan;
private boolean nutFree;
private boolean glutenFree;
public Ingredient(boolean vegan, boolean nutFree, boolean glutenFree) {
this.vegan = vegan;
this.nutFree = nutFree;
this.glutenFree = glutenFree;
}
#Override
public boolean isVegan() {
return vegan;
}
#Override
public boolean isNutFree() {
return nutFree;
}
#Override
public boolean isGlutenFree() {
return glutenFree;
}
}
Your Filling:
public class Filling extends Ingredient {
public Filling(boolean vegan, boolean nutFree, boolean glutenFree) {
super(vegan, nutFree, glutenFree);
}
}
Your Topping:
public class Topping extends Ingredient {
public Topping(boolean vegan, boolean nutFree, boolean glutenFree) {
super(vegan, nutFree, glutenFree);
}
}
And your Wrap:
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Wrap {
private List<Filling> fillings;
private List<Topping> toppings;
public Wrap(List<Filling> fillings, List<Topping> toppings) {
this.fillings = fillings;
this.toppings = toppings;
}
public boolean isNutFree() {
return testIngredient(FoodInformation::isNutFree);
}
public boolean isVegan() {
return testIngredient(FoodInformation::isVegan);
}
public boolean isGlutenFree() {
return testIngredient(FoodInformation::isGlutenFree);
}
private boolean testIngredient(Predicate<FoodInformation> predicate) {
// edited thanks to davidxxx for the Stream.concat notation!
return Stream
.concat(fillings.stream(), toppings.stream())
.allMatch(predicate);
}
}
And a test to show the implementation works:
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertFalse;
public class WrapTest {
private Wrap wrap;
#Before
public void setup() {
Filling filling1 = new Filling(true, true, false);
Filling filling2 = new Filling(true, false, true);
Filling filling3 = new Filling(true, true, true);
Topping topping1 = new Topping(true, true, true);
wrap = new Wrap(Arrays.asList(filling1, filling2, filling3), Collections.singletonList(topping1));
}
#Test
public void testIsGlutenFree() {
assertFalse(wrap.isGlutenFree());
}
#Test
public void testIsNutFree() {
assertFalse(wrap.isNutFree());
}
#Test
public void testIsVegan() {
assertTrue(wrap.isVegan());
}
}
Have fun with your project!
create an interface that has isVegan and isNutFree
public interface MyInterface {
boolean isVegan();
boolean isNutFree();
}
Then each of your classes with implement your interface
public class Topping implements MyInterface {
#Override
public boolean isVegan() {
return isVegan;
}
#Override boolean isNutFree() {
return isNutFree;
}
}
public class Filling implements MyInterface {
#Override
public boolean isVegan() {
return isVegan;
}
#Override boolean isNutFree() {
return isNutFree;
}
}
Next create a method that can test the lists
public boolean isVegan(List<? extends MyInterface> list) {
for(MyInterface myObj : list) {
if (myObj.isVegan()) return true;
}
return false;
}
public boolean isNutFree(List<? extends MyInterface> list) {
for(MyInterface myObj: list) {
if (myObj.isNutFree()) return true;
}
return false;
}
then each list you can pass into the methods to get the results
Related
I have a program that can print a pizza with decorators. I have an interface:
public interface PizzaPie{
String top();
}
And an implementation of the interface
public class PizzaPieImplementation implements PizzaPie{
#Override
public String top() {
return "Pie of pizza";
}
}
And an abstract class that implements it with the same object.
public abstract class PizzaTopper implements PizzaPie{
private PizzaPie pizza;
#Override
public String top() {
return pizza.top();
}
}
And I have several decorator classes, such as
public class Onions extends PizzaTopper{
public Onions(PizzaPie pizza) {
super(pizza);
}
public String top() {
return super.top() + topWithOnions();
}
private String topWithOnions() {
return " with onions";
}
And similar classes for peppers, pepperoni, anchovies, pineapple, etc.
I have a list as follows:
List<String> toppings = {onions, pineapple};
Is there a way to take each topping from the toppings list, and use that to create a new pizza with those toppings, to return something like:
Pie of pizza with onions with pineapple
The method would look something like this:
public PizzaPie CreatePizzaWithUserInput(List<String> toppings) {
//code
}
And ultimately it would create code that looks like this:
PizzaPie pizza1 = new Onion(new Pineapple(new PizzaPieImplementation()));
In theory this can be done with a lot of ugly if statements but I'm wondering if there's a quicker way of doing it.
You can use Java Reflection to achieve this.
Here we build our factory with the different possibilities of toppings, then we create a Pizza using createPizzaWithUserInput.
In this example we built a pizza with 3 of the four possible toppings.
Notice that to add a new Topping possibility you just extends PizzaTopper and add it on the toppingOptions on the PizzaFactory instantiation.
import java.util.List;
import java.util.LinkedList;
class Main {
public static void main(String[] args) {
// Possibilities
PizzaFactory pizzaFactory = new PizzaFactory(Onions.class, Bacon.class, Olives.class, Tomatos.class);
// User input
List<String> toppings = new LinkedList<String>();
toppings.add("onions");
toppings.add("olives");
toppings.add("bacon");
try{
PizzaPie pizza = pizzaFactory.createPizzaWithUserInput(toppings);
System.out.println(pizza.top());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here we have the PizzaFactory. We use the class' name to do the matching with the topping option, but you can customize it if you want (to match also "onion"/"onions" or "tomato"/"tomatos" for instance).
import java.util.List;
import java.util.Arrays;
import java.lang.reflect.*;
public class PizzaFactory {
List<Class<? extends PizzaTopper>> toppingOptions;
public PizzaFactory(Class<? extends PizzaTopper>... toppingOptions) {
this.toppingOptions = Arrays.asList(toppingOptions);
}
public PizzaPie createPizzaWithUserInput(List<String> toppings) throws NoSuchMethodException, InstantiationException, IllegalAccessException,InvocationTargetException {
PizzaPie pizza = new PizzaPieImplementation();
for(String toppingName : toppings) {
for(Class<? extends PizzaTopper> top : toppingOptions) {
if(top.getName().toLowerCase().equals(toppingName.toLowerCase())) {
Constructor<? extends PizzaPie> constructor = top.getConstructor(PizzaPie.class);
pizza = constructor.newInstance(pizza);
}
}
}
return pizza;
}
}
Here we have the interface PizzaPie:
public interface PizzaPie{
String top();
}
And its implementation.
public class PizzaPieImplementation implements PizzaPie{
#Override
public String top() {
return "Pie of pizza";
}
}
The decorator class.
public abstract class PizzaTopper implements PizzaPie{
private PizzaPie pizza;
protected PizzaTopper(PizzaPie pizza) {
this.pizza = pizza;
}
#Override
public String top() {
return pizza.top();
}
}
Tomatos topping.
public class Tomatos extends PizzaTopper{
public Tomatos(PizzaPie pizza) {
super(pizza);
}
public String top() {
return super.top() + topWithOnions();
}
private String topWithOnions() {
return " with tomatos";
}
}
Onions topping.
public class Onions extends PizzaTopper{
public Onions(PizzaPie pizza) {
super(pizza);
}
public String top() {
return super.top() + topWithOnions();
}
private String topWithOnions() {
return " with onions";
}
}
Olives topping
public class Olives extends PizzaTopper{
public Olives(PizzaPie pizza) {
super(pizza);
}
public String top() {
return super.top() + topWithOnions();
}
private String topWithOnions() {
return " with olives";
}
}
Bacon topping.
public class Bacon extends PizzaTopper{
public Bacon(PizzaPie pizza) {
super(pizza);
}
public String top() {
return super.top() + topWithOnions();
}
private String topWithOnions() {
return " with bacon";
}
}
You could just make the member variable stored in PizzaTopper an array, and its constructor accept (PizzaPie... pizzas). Then, you could pass in an array of pizzas/toppings (anything implementing PizzaPie) and PizzaTopper.top() could return a runtime-generated concatenation of all of the PizzaPies' top() results.
I'm wondering if the Interface segregation principle applys to my codebase.
Here's some example code:
First Class:
public class EntityGroup {
public List<Entity> tests;
//returns true if the EntityGroup is valid
public boolean validate() {
for (Entity test : tests) {
if (!test.validateFieldA() || !test.validateFieldB()) {
return false;
}
}
return true;
}
}
Second Class:
public abstract class Entity {
protected String fieldA;
public abstract boolean validateFieldA();
public abstract boolean validateFieldB();
}
Third Class:
public class EntityChild extends Entity {
private String fieldB;
#Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
#Override
public boolean validateFieldB() {
if (fieldB.equals("valid")) {
return true;
} else {
return false;
}
}
}
Fourth Class:
public class EntityChild2 extends Entity {
#Override
public boolean validateFieldA() {
if (fieldA.equals("valid")) {
return true;
} else {
return false;
}
}
#Override
public boolean validateFieldB() {
return true;
}
}
This is a greatly simplified example from my real codebase but I think it illustrates the problem well. My EntityChild2 class is forced to implement a method it does not need or want to know about.
I know that it would be more correct to have a Interface that would contain the validateFieldB() method and only have EntityChild implement that interface.
With the understanding that this would take a significant amount of effort to refactor into this solution, I'm having a hard time justifying the time it would take to implement this solution in my real code base.
What potential problems will I run into down the line by leaving my code this way?
What benefits will I gain from refactoring my code to have a separate interface for validateFieldB()?
tldr: Why is the Interface Segregation Principle so important?
Wrong Abstraction
You make use of the interface segregation principle but with wrong abstractions.. Your different Entity-types differ only in they behavior.
Because of the shared behavior you have duplicate code in the methods validateFieldA of EntityChild and EntityChild2 . The method validateFieldB looks very similar to validateFieldA just the filed for checking the equality is an other.
You only need one Entity
Strategy Pattern
With the Strategy-Pattern you will have no duplicate code:
class EqualValidationStategy() implements ValidationStategy<T> {
#Override
public boolean check(T a, T b) {
return a.equals(b)
}
}
class TrueValidationStategy() implements ValidationStategy<T> {
#Override
public boolean check(T a, T b) {
return true;
}
}
Entity
public class Entity {
private String fieldA;
private String fieldB;
private ValidationStategy<String> validationForA;
private ValidationStategy<String> validationForB;
// all-args consturctor
#Override
public boolean validateFieldA() {
return validationForA.check(fieldA, "valid");
}
#Override
public boolean validateFieldB() {
return validationForB.check(fieldB, "valid");
}
}
// Validates fieldA and "ignores" fieldB
Entity example = new Entity(fieldA,
fieldB,
new EqualValidationStategy(),
new TrueValidationStategy());
I created a java project to apply my GraphTheory course and enhance my java skills.
In this project :
I created a class Sommet<S>(Vertex in English) with an attribute Id with a generic type called <S>.
I created a class Arc<S>(Edge in English) with two attributes Sommet(Vertex).
I created a class EnsembleArc which is an HashSet of Arc
I also created a class ArcValue which inherit from Arc and have an int attribute Valeur(Value in English)
Here everything is fine and I dont have any problem.
But then I created a class EnsembleArcValue which inherit from EnsembleArc because every method from EnsembleArc will be useful to EnsembleArcValue.
But I also want EnsembleArcValue to be an HashSet of ArcValue (and I dont want an Arc which is not an ArcValue). And with the inheritance EnsembleArcValue is able to have an "simple" Arc in his Set.
So my question after all this explanation is :
Is there a way for EnsembleArcValue to inherit from EnsembleArc but will only accept an ArcValue in his Set.
Here is an image of The UML Project
I hope it will help to understand my problem (dont look at the bottom).
Here is the code :
public class Sommet<S>
{
//attributes
private S id;
public Sommet(S s)
{
setId(s);
}
public S getId()
{
return id;
}
public void setId(S s)
{
assert s!= null: "Objet null passé en paramètre";
id = s;
}
#SuppressWarnings("unchecked")
#Override
public boolean equals(Object obj)
{
boolean callback;
if(obj.getClass()!=getClass())
{
callback=false;
}
else
{
if(((Sommet<S>)obj).getId().equals(getId()))
{
callback=true;
}
else
{
callback=false;
}
}
return callback;
}
#Override
public int hashCode()
{
return getId().hashCode();
}
#Override
public String toString()
{
return getId().toString();
}
}
public class Arc<S>
{
private Sommet<S> depart;
private Sommet<S> arrivee;
public Arc(Sommet<S> dep, Sommet<S> arr)
{
setDepart(dep);
setArrivee(arr);
}
#Override
public String toString()
{
String str="("+getDepart().getId()+","+getArrivee().getId()+")";
return str;
}
public Sommet<S> getDepart()
{
return depart;
}
public Sommet<S> getArrivee()
{
return arrivee;
}
public void setDepart(Sommet<S> depart)
{
this.depart = depart;
}
public void setArrivee(Sommet<S> arrivee)
{
this.arrivee = arrivee;
}
#SuppressWarnings("unchecked")
#Override
public boolean equals(Object obj)
{
boolean callback;
if(obj.getClass()!=getClass())
{
callback=false;
}
else
{
if(((Arc<S>)obj).getDepart().equals(getDepart())&&((Arc<S>)obj).getArrivee().equals(getArrivee()))
{
callback=true;
}
else
{
callback=false;
}
}
return callback;
}
#Override
public int hashCode()
{
return getArrivee().hashCode()+getDepart().hashCode();
}
}
public class ArcValue<S,V> extends Arc<S>
{
private V valeur;
public ArcValue (Sommet<S> depart, Sommet<S> arrivee, V valeur)
{
super(arrivee,depart);
this.valeur=valeur;
}
public V getValeur()
{
return valeur;
}
}
import java.util.HashSet;
public class Ensemble<E> extends HashSet<E> implements Cloneable
{
private static final long serialVersionUID = -4354387895748449845L;
public Ensemble ()
{
super();
}
public Ensemble (Ensemble<E> ensemble)
{
for (E e : ensemble)
{
add(e);
}
}
public String toString()
{
StringBuffer str=new StringBuffer("{");
for(E e: this)
{
str=str.append(e.toString()+",");
}
str.setCharAt(str.length()-1, '}');
return str.toString();
}
#SuppressWarnings("unchecked")
#Override
public Ensemble<E> clone()
{
return (Ensemble<E>)super.clone();
}
}
public class EnsembleArc<S> extends Ensemble<Arc<S>>
{
public EnsembleArc(Ensemble<Arc<S>> ensemble)
{
super(ensemble);
}
public EnsembleArc()
{
super();
}
private static final long serialVersionUID = -4099925554493145279L;
public EnsembleSommet<S> listSucc(Sommet<S> sommet)
{
EnsembleSommet<S> XSucc=new EnsembleSommet<S>();
for (Arc<S> arc : this)
{
if (arc.getDepart()==sommet)
{
XSucc.add(arc.getArrivee());
}
}
return XSucc;
}
public EnsembleSommet<S> listPred(Sommet<S> sommet)
{
EnsembleSommet<S> XPred=new EnsembleSommet<S>();
for (Arc<S> arc : this)
{
if (arc.getArrivee()==sommet)
{
XPred.add(arc.getDepart());
}
}
return XPred;
}
public void add(Sommet<S> depart,Sommet<S>arrivee)
{
add(new Arc<S>(depart,arrivee));
}
#Override
public EnsembleArc<S> clone ()
{
return (EnsembleArc<S>)super.clone();
}
}
//import java.util.Collection;
public class EnsembleArcValues<S,V> extends EnsembleArc<S> //implements Collection<ArcValue<S,V>>
{
//TODO faire en sorte que ensembleArcValués ne contienne que des ArcsValue
private static final long serialVersionUID = -7163498825360866323L;
}
And you'll need this one to :
public class EnsembleSommet<S> extends Ensemble<Sommet<S>>
{
public EnsembleSommet()
{
super();
}
public EnsembleSommet(EnsembleSommet<S> ensemble)
{
super(ensemble);
}
private static final long serialVersionUID = 7278825382690341067L;
#Override
public EnsembleSommet<S> clone ()
{
return (EnsembleSommet<S>)super.clone();
}
public Sommet<S> firstSommet()
{
#SuppressWarnings("unchecked")
Sommet<S>[] tab=new Sommet[size()];
return toArray(tab)[0];
}
}
The only way you can achieve this is to make the type of Arc you want part of your generic deceleration. Rename your existing EnsembleArc to AbstractEnsembleArc and change it's generic decleration from < S > to < S, T extends Arc< S > > i.e.:
public abstract class AbstractEnsembleArc<S, T extends Arc<S>> extends Ensemble<T> {
// PUT ALL YOUR LOGIC CURRENTLY IN EnsembleArc HERE
}
Now create a new Class Called EnsembleArc and extend the new abstract class you've added, this new class will work identically to your existing EnsembleArc and class decleration should now look like:
public class EnsembleArc<S> extends AbstractEnsembleArc<S, Arc<S>> {
}
Finally have EnsembleArcValues extend the Abstract class instead of EnsembleArc so that you can declare that it should only accepts ArcValue and not simple Arc, do that like this:
public class EnsembleArcValues<S, V> extends AbstractEnsembleArc<S, ArcValue<S, V>> {
}
So, after this question where I basically exploits reflection for passing primitive references to modify the primitive itself, like:
_begin("Another Window", ::showAnotherWindow)
I was looking for something to make something similar possible also from java, where at the moment I am using plains primitive arrays:
private boolean[] showAnotherWindow = {false};
imgui.begin("Another Window", showAnotherWindow);
#hotkey suggested me the possibility to create a class implementing the KMutableProperty0 interface and that automatically gets and sets the corresponding variable
Example:
KMutableProperty0<Boolean> prop =
PropUtils.javaProp(this, t -> t.showAnotherWindow, (t, r) -> { t.showAnotherWindow = r; });
_begin("Another Window", prop);
So, I wanted to give it a try and implemented the following in java.
Getter:
#FunctionalInterface
public interface Getter<T> {
T get();
}
Setter:
#FunctionalInterface
public interface Setter<T> {
void set(T type);
}
And then the class itself (I just wrote the constructor, all the methods are those requested by the interface and automatically implemented by the IDE) :
public class JavaProp <T> implements KMutableProperty0<T> {
private imgui.Getter<T> getter;
private imgui.Setter<T> setter;
public JavaProp(imgui.Getter<T> getter, imgui.Setter<T> setter) {
this.getter = getter;
this.setter = setter;
}
#Override
public void set(T t) {
setter.set(t);
}
#NotNull
#Override
public Setter<T> getSetter() {
return null;
}
#Override
public T get() {
return getter.get();
}
#Nullable
#Override
public Object getDelegate() {
return null;
}
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
#Override
public T invoke() {
return null;
}
#Override
public boolean isLateinit() {
return false;
}
#Override
public boolean isConst() {
return false;
}
#NotNull
#Override
public String getName() {
return null;
}
#NotNull
#Override
public List<KParameter> getParameters() {
return null;
}
#NotNull
#Override
public KType getReturnType() {
return null;
}
#NotNull
#Override
public List<KTypeParameter> getTypeParameters() {
return null;
}
#Override
public T call(Object... objects) {
return null;
}
#Override
public T callBy(Map<KParameter, ?> map) {
return null;
}
#Nullable
#Override
public KVisibility getVisibility() {
return null;
}
#Override
public boolean isFinal() {
return false;
}
#Override
public boolean isOpen() {
return false;
}
#Override
public boolean isAbstract() {
return false;
}
#NotNull
#Override
public List<Annotation> getAnnotations() {
return null;
}
}
But whenever I try to run that, I get the following:
Error:(45, 12) java: reference to Getter is ambiguous
both interface kotlin.reflect.KProperty0.Getter in kotlin.reflect.KProperty0 and interface kotlin.reflect.KProperty.Getter in kotlin.reflect.KProperty match
The problematic function is this one:
#NotNull
#Override
public Getter<T> getGetter() {
return null;
}
And the relevant file is kotlin.reflect.KProperty.tk, you can find it here
Any idea how could I solve it?
Just specify which interface you mean:
public KProperty0.Getter<T> getGetter()
But I would prefer to implement the class in Kotlin and only consume it from Java.
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));
}
}