Which design pattern is most appropriate, if any - java

So, this element of code has the potential to get pretty ugly. There is the potential of adding multiple elements to the list in each if statement as well as many more if/else statements. What would be the best pattern or way of going about designing this piece of code. I was thinking about the chain of responsibility but that means be passing the list round everywhere which isn't the best or even the builder pattern? Any thoughts??
List<String> aList = new ArrayList<>();
if (something.contains(Effect.HARD)) {
aList.add("");
}
if (something.contains(Effect.REFLECT)) {
aList.add("");
aList.add("");
} else {
aList.add("no reflect");
}
if (something.contains(Effect.OUTLINE)) {
aList.add("something");
}
if (something.contains(Effect.GRADIENT)) {
aList.add("gradient");
} else {
aList.add("no gradient");
}

Use a visitor (link to wikipedia page).
Here is some lighthearted example code:
public interface Visilator
{
// Process the stuff and, maybe, add an element to the kerplungy list.
void doStuff(Stuff stuff, List<Kerplungy> kerplungyList);
}
public class Kerplungilator
{
// Actually create this however you choose.
#Autowired
private List<Visilator> visilatorList;
public List<Kerplungy> processStuffs(final Stuff stuff)
{
final List<Kerplungy> returnValue = LinkedList<>(); // ArrayList is for chumps.
for (final Visilator current : visilatorList)
{
current.doStuff(Stuff, returnValue);
}
return returnValue;
}
}
public clss HootVisilator
implements Visilator
{
public void doStuff(
#NotNull final Stuff stuff,
#NotNull final List<Kerplungy> kerplungyList)
{
if (stuff.hoot())
{
final Kerplungy hootKerplungy = new Kerplungy("hoot");
kerplungyList.add(hootkerplungy);
}
else
{
System.out.println("not hoot");
}
}
}

Normally you'd look at replacing those ugly conditionals with polymorphic code, but that won't work well here as the conditions (something.contains(...)) are not based on the type of the object. You could turn them into objects, but this would not be an elegant solution either. Builder and Visitor could be used, but I doubt very much you code would more readable at all.

Related

How to avoid changing many parts of code when adding new enum value, thus providing easier extensibility?

I am trying to make my code easier to extend in terms that a little change will not affect much other code.
I have an enum MyEnum, which values might increase in future.
Then, there are classes that holds instance of it and has many behaviors affected by that enum's concrete value. In other words, there are many places where I switch over it's value.
public enum MyEnum
{
FIRST, SECOND, THIRD, FOURTH;
}
public class A
{
private MyEnum myEnum
public A(MyEnum myEnum)
{
this.myEnum = myEnum;
}
// as you will see, there is a lot of switching over its value
public void boo()
{
switch(myEnum)
{
case FIRST: // do smtng
case SECOND: // do smthing else
case THIRD: // do smthing else
case FOURTH: // do nice thing
}
}
public int goo()
{
switch(myEnum)
{
...
}
}
public AnotherObject foo()
{
switch(myEnum)
{
...
}
}
}
public class B
{
private MyEnum myEnum
public B(MyEnum myEnum)
{
this.myEnum = myEnum;
}
public double doo()
{
switch(myEnum)
{
...
}
}
public void soo()
{
switch(myEnum)
{
...
}
}
public boolean xoo()
{
switch(myEnum)
{
...
}
}
}
The thing here is that mostly I will need to add new case to all places where we switch over it's value => will need to do many changes to code when I add new enum value.
Did anyone else faced this problem? By now, I guess it is just downside of using enums this way.
Don't bind your code to the enum bind your code to an interface. Then have your enum provide the standard implementations of the interface.
public interface RibbonColor {
public String getColor();
}
public enum DefaultRibbonColors implements RibbonColor {
FIRST() {
public String getColor() {
return "blue";
}
},
SECOND() {
public String getColor() {
return "red";
}
},
THIRD() {
public String getColor() {
return "white";
}
},
}
public class Awards {
private List<RibbonColor> ribbons;
public Awards(List<RibbonColor> ribbons) {
this.ribbons = ribbons;
}
public RibbonColor awardFor(int placeIndex) {
if (placeIndex < ribbons.length()) {
return ribbons.get(placeIndex).getColor();
}
return null;
}
}
Notice that now you can easily add in a new list of all the default Awards by
Awards awards = new Awards(Arrays.asList(DefaultRibbonColors.values()));
while you could also create custom awards sets.
List ribbons = new ArrayList<RibbonColor>();
ribbons.addAll(DefaultRibbonColors.values());
ribbons.addAll(ExtendedRibbonColors.values());
ribbons.addAll(new BlackAndPinkPolkaDotRibbonColor());
Awards awards = new Awards(ribbons);
The key is to never make the code actually depend on the enum because you can't modify an enum without recompiling, and that triggers the need to search for switch statements that lack default: blocks or more explicit settings for the added value.
Objects are "code and data written together" while procedural code is "code and data managed separately" The switch statement puts the logic "code" outside of the type "data" and is a programming mistake in 100% insanely object oriented design. That said, it is often useful, and people still structure programs in Java and other languages in ways that effectively separate code from data (object that hold all the data, and "object routines" that manipulate another object's data. This kind of separation of an object's data from its routines is an antipattern called anemic objects.
Enums are Objects so don't be afraid to put methods in them! Give them interfaces where they should be replicable, and avoid switch statements because it's probably a good sign that the logic should be in the thing you are switching on (provided it is an Object).

If/else representation with stream and Java 8

I have the following interface with two implementations:
public interface Parser {
void parse();
boolean canParse(String message);
}
class StackParser implements Parser {
public void parse(){
System.out.println("Parsing stackoverflow");
}
public boolean canParse(String message){
return message.equals("stackoverflow");
}
}
class YoutubeParser implements Parser {
public void parse() {
System.out.println("Parsing youtube");
}
public boolean canParse(String message) {
return message.equals("youtube");
}
}
I go to check incoming message and parse "stackoverflow" or "youtube":
public class Main {
private List<Parser> parsers;
public static void main(String[] args) {
new Main().doSomething("youtube");
}
void doSomething(String message){
parsers.stream()
.filter(p -> p.canParse(message))
.forEach(p -> p.parse());
}
}
Okay, pretty good. But what if message is not "stackoverflow" or "youtube"? App will be silent, but I want to send another default message if no matches were found, like "I can't parse this web!".
I know that will not works (even compile), but it's also should print "I can't parse this web" only one time, not for every false condition.
parsers.stream()
.filter(p -> {
if (p.canParse(message) == false) {
System.out.println("I can't parse it!");
}
})
.forEach(p -> p.parse());
How can I do it?
This is a perfect example of when to use the Optional#orElse or the Optional#orElseThrow method(s). You want to check if some condition is met so you filter, trying to return a single result. If one does not exist, some other condition is true and should be returned.
try {
Parser parser = parsers.stream()
.filter(p -> p.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
In case only one parser can parse the message at a time you could add a default parser:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
And then use it via
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
or alternatively drop the DefaultParser and just do
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}
You can use simply a forEach if-else inside
parsers.forEach(p -> {
if (!p.canParse(message)) {
System.out.println("I can't parse it!");
} else {
p.parse();
}
});
That's a pretty interesting question, which fortunately I had to face some time ago.
Mi approach consisted on declaring a list of Supplier<T> which would be iterated only if there's and exception thrown (the intention of this approach was to retrieve data from DB based on the parameters given, so I would be able to search by id or by an instance).
import java.util.function.Supplier;
public class AbstractFacadeUtil {
public <R> R tryOr(Supplier<R>...fns) {
R result = null;
boolean success = false;
int i = 0;
while (!success && i < fns.length) {
Supplier<R> fn = fns[i++];
try {
result = fn.get();
success = true;
} catch (Exception e) {
}
}
if (!success) {
throw new RuntimeException(new Exception(String.format("[%s] Couldn't find a successful method to apply\"", this.getClass())));
}
return result;
}
}
Some notes:
I'd used Supplier<T> because it's body didn't contain anything that would throw an undeclared exception which, otherwise, would be needed to use Callable<T> instead.
Yeah, could have given it a better name though.
Maybe an Iterator<T> would make that piece of code more understandable and clean.
In your specific case, I'd use Jason's approach by adding a Supplier<T> at the end of the list that would throw an NoParserFoundException
[EDIT]
Also, you should iterate the List<Supplier<T>> or List<Callable<T>> wheter the Parser can't parse and it throws an CantParseException.
So, as you see, exceptions can help a lot even I'm not sure this would be the most efficient or expert approach.
Hope it helps you.
[EDIT2]
This is an example of how I implemented the solution given above.
Ok, I'm gonna say it. Look at every solution posted - what do you think? Are they neat, clean code that you would expect from functional approach?
Nope, why? Because the design is wrong, it doesn't fit functional approach.
Fix the design:
get rid of void return type (brr)
don't overuse methods like canDoSomething (treat them like isPresent in Optional - it's there for extreme cases, mostly technical, not business code)
look into VAVR (or similar library) - classes like Try, Either etc.
Solution will come naturally then and in every case - not only this specific one you posted here.

Best Practice on Where to Perform Iteration

I've come across the following code at work and it raised a question in my mind.
\\Option 1
public class MyObjectRegistry
{
private MyObjectMapper mapper = new MyObjectMapper();
public void StoreMyObjects (List<MyObject> myObjectList)
{
mapper.StoreMyObjects(myObjectList);
}
}
public class MyObjectMapper
{
public void StoreMyObjects(List<MyObject> myObjectList)
{
for (MyObject myObj : myObjectList)
{
//Store Object In Database
}
}
}
vs
\\Option 2
public class MyObjectRegistry
{
private MyObjectMapper mapper = new MyObjectMapper();
public void StoreMyObjects (List<MyObject> myObjectList)
{
for (MyObject myObj : myObjectList)
{
mapper.StoreMyObject(myObj);
}
}
}
public class MyObjectMapper
{
public void StoreMyObject(MyObject myObject)
{
//Store Object In Database
}
}
Option 1 is currently what is in the code base. My question is: Is one of these approaches better than the other? Are there any conventions or best practices regarding a situation like this regarding where the iteration should take place?
The first one should definitely be preferred. The second example keeps calling an external method which is much more resource demanding than the first due to the abstraction involved. The lower level you can keep your iterations the better.
The way it is now, with a List in the method signature, should definitely be preferred because the performance of database insertion is dramatically better with insert batching. With the code designed as in the second example, batching would be a great pain to implement, which means it probably wouldn't be implemented.

Casting objects when returning a generics list

I'm relatively new to Java and generics. I'm trying to understand if I'm doing something wrong or not in writing a generic method. I have the following code (greatly simplified):
public class ContentIniter {
public ContentType getContentType();
}
public interface Content {
}
public class Show implements Content {
}
public class Movie implements Content {
}
public enum ContentType {
Movie, Show
}
public class Channel {
public List<Show> getShows() {
return getContentByType(ContentType.Show)
}
public List<Movie> getMovies() {
return getContentByType(ContentType.Movie)
}
private <T> List<T> getContentByType(ContentType contentType) {
List<T> typeContents = Lists.newArrayList();
List<ContentIniter> allContentIniters = someMethod(); // Returns initers for both shows and movies
for (Content contentIniter : allContentIniters) {
if (contentIniter.getContentType().equals(contentType)) {
switch (contentType) {
case Movie:
typeContents.add((T) new Movie(contentIniter));
break;
case Show:
typeContents.add((T) new Show(contentIniter));
break;
}
}
}
return typeContents;
}
}
My question relates to the line:
typeContents.add((T) new Movie(contentIniter));
The only way I've been able to get the code to compile is if I cast the content object to T. But that seems yucky to me (and I don't understand why the compiler can't infer the type based on the calls). Moreover, even though the code works, IntelliJ complains of an unchecked cast.
Is there a better way to write the generic method?
UPDATE: Screwed up the code a bit when I tried to simplify it. Fixed the reference to typeContents. Also, I added a bit more complexity so that it better reflects the reality, in hopes of explaining why I wasn't simply checking for instanceof.
UPDATE 2: Realized there was yet another error...ContentIniter doesn't implement Content. It's also worth noting, ContentIniter is just a made up object. If it seems weird, think of it as an Event or other Strategy that Content objects use to delegate certain behaviors.
You're not using generics properly, you're mixing them with your enumeration when it's really not necessary. Ideally you would be calling getContentByType<Show>() and then determine the list of the correct type from allContents using reflection.
Try something more along the lines of like (untested):
private <T> List<T> getContents() {
List<T> typeContents = Lists.newArrayList();
List<Content> allContents = someMethod(); // Returns both shows and movies
for (Content content : allContents) {
if (content instanceof T) {
typeContents.add((T) content);
}
}
return typeContents;
}
And call:
List<Show> shows = getContents<Show>();
You can then restrict the types that are called on it to only those that extend Content.
private <T extends Content> List<T> getContents() {
...
}
Actually the answer is simpler than you think : you just have to check whether your instance of Content is a Show or a Movie to make your compiler happy :
if (content instanceof Movie)
contents.add((Movie) content);
if (content instanceof Show)
contents.add((Show) content);
Anyway, I would say that the way that you wrote your generic method is correct. But since there is a native way to check for the type of an instance (instanceof), you should use it :)
EDIT : I still think you should use instanceof.
Plus, you should use a List<Content> instead of a List<ContentIniter>, because Content is a more global type : if someone comes up with another implementation of Content, he won't have to change your code. Actually, you're doing the same thing when you use the Interface List instead of an ArrayList for example, because List is less specific than ArrayList.
Also, using an enum is not a mistake : if you want to use one, you can. But it shouldn't be used to determine the type of an instance. The type of an instance is contained in the instance itself, period. Still, I'll say that Daniel Imms' solution is more elegant than mine, and takes better advantage of Java type features.
public interface Content {
public STContentType getContentType();
}
public class ContentIniter implements Content {
}
// You can keep the enum, as long as it's not used
// to check for the type of an instance of ContentIniter
public enum ContentType {
Movie, Show
}
public class Show implements Content {
}
public class Movie implements Content {
}
public class Channel {
public List<Show> getShows() {
return getContentByType(ContentType.Show)
}
public List<Movie> getMovies() {
return getContentByType(ContentType.Movie)
}
private <T> List<T> getContentByType(ContentType contentType) {
List<T> typeContents = Lists.newArrayList();
// Using more generic type Content
List<Content> allContentIniters = someMethod(); // Returns initers for both shows and movies
for (Content contentIniter : allContentIniters) {
// If it's a Show and I asked for Shows
if (contentIniter instanceof Show && contentType == ContentType.Show)) {
typeContents.add(contentIniter);
}
// If it's a Movie and I asked for Movies
if (contentIniter instanceof Movie && contentType == ContentType.Movie){
typeContents.add(contentIniter);
}
}
return typeContents;
}
}
Use of enum seems strange here and the way you do lost advantage of using generics.
The initer things is making things even more strange and messy.
It may looks more natural with something like this:
public interface Content {
}
public class Show implements Content {
}
public class Movie implements Content {
}
//......
private <T extends Content> List<T> getContentByType(Class<T> contentType) {
List<T> result = Lists.newArrayList();
List<Content> allContents = someMethod(); // ContentIniter is just a mess
// Get all content you have!
for (Content content: contents) {
if (contentType.isAssignableFrom(content.getClass())) {
result.add(content);
}
}
return result;
}
The way to use is
List<Show> result = channel.getContent(Show.class);
I removed my original answer after the code example change.
I really don't think you can avoid the cast and the #SuppressWarnings("unchecked").
As long as you know what you're doing, this is probably the best solution.
The alternative is to do without the getByContentType method and just have a bit of duplicated logic on the getShows() and getMovies() methods.
For example:
public List<Show> getShows() {
List<Show> shows = new ArrayList<Show>();
List<ContentIniter> allContentIniters = someMethod();
for(ContentIniter initer: allContentIniters) {
if(initer.getContentType().equals(ContentType.Show)) {
shows.add(new Show(initer));
}
}
return shows;
}
public List<Movie> getMovies() {
List<Movie> movies = new ArrayList<Movie>();
List<ContentIniter> allContentIniters = someMethod();
for(ContentIniter initer: allContentIniters) {
if(initer.getContentType().equals(ContentType.Movie)) {
movies.add(new Movie(initer));
}
}
return movies;
}

In Java, need to make variables available to Control Break solution

Below is an attempt to create a reusable solution for the control break pattern. It is built on Command Pattern (Action and Test interfaces). However, I realized my old COBOL thinking got in the way, because this solution is predicated on each of the Action and Test objects having access to "global variables." And my immediate thought after that was "the need for variable access like this (wider scope) must be an already invented wheel.
How to give all the Actions and Tests below access to a group of variables -- an indeterminate group because this is supposed to be a reusable solution??
public class ControlBreak {
public static void controlBreak(Action initialize,
Test endOfInput,
Test onChange,
Action breakAction,
Action detailAction,
Action getNext) {
boolean hasProcessed = false;
getNext.execute();
for (initialize.execute();endOfInput.test();detailAction.execute(),getNext.execute()) {
hasProcessed = true;
if (onChange.test()) {
breakAction.execute();
}
detailAction.execute();
}
if (hasProcessed) {
breakAction.execute();
} else {
// throw empty input exception
}
}
}
On a few re-reads, it seems like you're trying to abstract a certain control flow, where the parameters can be coupled. In this case, I'd look into generics. I.e. something like this:
public static void <TParams> controlBreak(Action<TParams> initialize, ..., TParams params) {
// ...
initialize.execute(params)
// ...
}
That way this method will remain reusable, but the various actions / tests can still accept a strongly-typed set of parameters/variables. (The concrete type of TParam.)
Thanks to millimoose, I got where I was going. Here's the fleshed out code, for reference:
public class ControlBreak<TParams> {
public TParams controlBreak(Action<TParams> initialize,
Test<TParams> endOfInput,
Test<TParams> onChange,
Action<TParams> breakAction,
Action<TParams> detailAction,
Action<TParams> getNext,
TParams params) {
boolean hasProcessed = false;
getNext.execute(params);
for (params = initialize.execute(params);endOfInput.test(params);params = detailAction.execute(params),params = getNext.execute(params)) {
hasProcessed = true;
if (onChange.test(params)) {
breakAction.execute(params);
}
detailAction.execute(params);
}
if (hasProcessed) {
breakAction.execute(params);
} else {
// throw empty input exception
}
return params;
}
}

Categories

Resources