Strategy Pattern too many if statements - java

A user enters a code and the type of that code is determined by regular expressions. There are many different type of codes, such as EAN, ISBN, ISSN and so on. After the type is detected, a custom query has to be created for the code. I thought it might be a good idea to create a strategy for type, but with time it feels wrong.
public interface SearchQueryStrategie {
SearchQuery createSearchQuery(String code);
}
-
public class IssnSearchQueryStrategie implements SearchQueryStrategie {
#Override
public SearchQuery createSearchQuery(final String code) {
// Create search query for issn number
}
}
-
public class IsbnSearchQueryStrategie implements SearchQueryStrategie {
#Override
public SearchQuery createSearchQuery(final String code) {
// Create search query for ISBN number
}
}
-
public class EanShortNumberSearchQueryStrategie implements SearchQueryStrategie {
#Override
public SearchQuery createSearchQuery(final String code) {
// Create search query for ean short number
}
}
-
public class TestApplication {
public static void main(final String... args) {
final String code = "1144875X";
SearchQueryStrategie searchQueryStrategie = null;
if (isIssn(code)) {
searchQueryStrategie = new IssnSearchQueryStrategie();
} else if (isIsbn(code)) {
searchQueryStrategie = new IsbnSearchQueryStrategie();
} else if (isEan(code)) {
searchQueryStrategie = new EanShortNumberSearchQueryStrategie();
}
if (searchQueryStrategie != null) {
performSearch(searchQueryStrategie.createSearchQuery(code));
}
}
private SearchResult performSearch(final SearchQuery searchQuery) {
// perform search
}
// ...
}
I have to say that there are many more strategies. How should I dispatch the code to the right strategy?
My second approach was to put a boolean method into every strategy to decide if the code is correct for that strategy.
public class TestApplication {
final SearchQueryStrategie[] searchQueryStrategies = {new IssnSearchQueryStrategie(), new IsbnSearchQueryStrategie(),
new EanShortNumberSearchQueryStrategie()};
public static void main(final String... args) {
final String code = "1144875X";
for (final SearchQueryStrategie searchQueryStrategie : searchQueryStrategie) {
if (searchQueryStrategie.isRightCode(code)) {
searchQueryStrategie.createSearchQuery(code);
break;
}
}
}
private SearchResult performSearch(final SearchQuery searchQuery) {
// perform search
}
// ...
}
How would you solve this problem? Is the strategy pattern the right one for my purposes?

If you are using Java 8 and you can profit from the functional features I think one Enum will be sufficient.
You can avoid using if/else statements by mapping each type of code with a Function that will return the query that needs to be executed:
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;
public enum CodeType
{
EAN("1|2|3"),
ISBN("4|5|6"),
ISSN("7|8|9");
String regex;
Pattern pattern;
CodeType(String regex)
{
this.regex = regex;
this.pattern = Pattern.compile(regex);
}
private static Map<CodeType, Function<String, String>> QUERIES =
new HashMap<>();
static
{
QUERIES.put(EAN, (String code) -> String.format("Select %s from EAN", code));
QUERIES.put(ISBN, (String code) -> String.format("Select %s from ISBB", code));
QUERIES.put(ISSN, (String code) -> String.format("Select %s from ISSN", code));
}
private static CodeType evalType(String code)
{
for(CodeType codeType : CodeType.values())
{
if (codeType.pattern.matcher(code).matches())
return codeType;
}
// TODO DON'T FORGET ABOUT THIS NULL HERE
return null;
}
public static String getSelect(String code)
{
Function<String, String> function = QUERIES.get(evalType(code));
return function.apply(code);
}
}
And in the main you can test your query:
public class Main
{
public static void main(String... args)
{
System.out.println(CodeType.getSelect("1"));
// System.out: Select 1 from EAN
System.out.println(CodeType.getSelect("4"));
// System.out: Select 4 from ISBB
System.out.println(CodeType.getSelect("9"));
// System.out: Select 9 from ISSN
}
}
I usually tend to keep the code as compact as possible.
Some people dislike enums, so I believe you can use a normal class instead.
You can engineer further the way you obtain the QUERIES (selects), so instead of having String templates you can have a Runnable there.
If you don't want to use the the functional aspects of Java 8 you can use Strategy objects that are associated with each type of code:
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;
public enum CodeType2
{
EAN("1|2|3", new StrategyEAN()),
ISBN("4|5|6", new StrategyISBN()),
ISSN("7|8|9", new StrategyISSN());
String regex;
Pattern pattern;
Strategy strategy;
CodeType2(String regex, Strategy strategy)
{
this.regex = regex;
this.pattern = Pattern.compile(regex);
this.strategy = strategy;
}
private static CodeType2 evalType(String code)
{
for(CodeType2 codeType2 : CodeType2.values())
{
if (codeType2.pattern.matcher(code).matches())
return codeType2;
}
// TODO DON'T FORGET ABOUT THIS NULL HERE
return null;
}
public static void doQuery(String code)
{
evalType(code).strategy.doQuery(code);
}
}
interface Strategy { void doQuery(String code); }
class StrategyEAN implements Strategy {
#Override
public void doQuery(String code)
{
System.out.println("EAN-" + code);
}
}
class StrategyISBN implements Strategy
{
#Override
public void doQuery(String code)
{
System.out.println("ISBN-" + code);
}
}
class StrategyISSN implements Strategy
{
#Override
public void doQuery(String code)
{
System.out.println("ISSN-" + code);
}
}
And the main method will look like this:
public class Main
{
public static void main(String... args)
{
CodeType2.doQuery("1");
CodeType2.doQuery("4");
CodeType2.doQuery("9");
}
}

So, The strategy pattern is indeed the right choice here, but strategy by itself is not enough. You have several options:
Use a Factory with simple if/else or switch. It's ugly, error prone to extend with new strategies, but is simple and quick to implement.
Use a registry. During the application initialization phase you can register in a registry each SearchQueryStratgeyFactory with the right code. For instance if you use a simple Map you can just do :
strategyRegistry.put("isbn", new IsbnSearchStrategyFactory());
strategyRegistry.put("ean", new EanSearchStrategyFactory());
.... and so on
Then when you need to get the right strategy you just get() the strategy factory from the map using the code id. This approach is better if you have a lot of strategies, but it requires an aditional iitialization step during the application startup.
Use a service locator. ServiceLocator is a pattern that enables the dynamic lookup of implementations. Java comes with an implementation of the ServiceLocator pattern -> the infamous ServiceLoader class. This is my favourite approach because it allows for complete decoupling of the consumer and implementation. Also using the service locator you can easily add new strategies without having to modify the existing code. I won't explain how to use the ServiceLoader - there is plenty of information online. I'll just mention that using the service locator you'll need to implement a "can process such codes ?" logic in each strategy factory. For instance if the factory cannot create a strategy for "isbn" then return null and try with the next factory.
Also note that in all cases you work with factories that produce the strategy implementations.
PS: It's strategy not strategie :)

Your approach is not the Strategy Pattern. Strategy Pattern is all about customizing behavior of an object (Context in terms of this pattern) by passing alternative Strategy object to it. By this way, we don't need to modify the source code of the Context class but still can customize the behavior of objects instanced from it.
Your problem is somewhat related to the Chain of Responsibility (CoR) Pattern where you have a request (your code) and need to figure out which SearchQueryStrategie in a predefined list should handle the request.
The second approach -- using array -- that you mentioned is fine. However, to make it usable in production code, you must have another object -- let's say Manager -- that manages the array and is responsible to find the relevant element for each request. So your client code have to depend on two objects: the Manager and the result SearchQueryStrategie. As you can see, the source code of Manager class tend to be changed frequently because new implementations of SearchQueryStrategie may come. This might make your client annoyed.
That's why the CoR Pattern uses the linked list mechanism instead of array. Each SearchQueryStrategie object A would hold a reference to a next SearchQueryStrategie B. If A cannot handle the request, it will delegate to B (it can even decorate the request before delegating). Of course, somewhere still must know all kinds of strategies and create a linked list of SearchQueryStrategie, but your client will then depend only on a SearchQueryStrategie object (the head one of the list).
Here is the code example:
class SearchQueryConsumer {
public void consume(SearchQuery sq) {
// ...
}
}
abstract class SearchQueryHandler {
protected SearchQueryHandler next = null;
public void setNext(SearchQueryHandler next) { this.next = next; }
public abstract void handle(String code, SearchQueryConsumer consumer);
}
class IssnSearchQueryHandler extends SearchQueryHandler {
#Override
public void handle(String code, SearchQueryConsumer consumer) {
if (issn(code)) {
consumer.consume(/* create a SearchQuery */);
} else if (next != null) {
next.handle(code, consumer);
}
}
private boolean issn(String code) { ... }
}

What i recommend is using the Factory pattern. It describes and handles your scenario better.
Factory Pattern

You can design in the following way (using concepts of factory DP and polymorphism):
Code as interface.
ISSNCode, ISBNCode and EANCode as concrete classes
implementing Code interface, having single-arg constructor taking text as String.
Code has method getInstanceOfCodeType(String text) which returns an instance of a sub-class of Code (decided by checking the type of text passed to it). Let's say the returned value be code
Class SearchQueryStrategieFactory with
getSearchQueryStrategie(code) method. It consumes the returned value from step 3, and generates different
instances of SearchQueryStrategie subclasses based on code type using new operator and, then returns the same.
So, you need to call two methods getInstanceOfCodeType(text) and getSearchQueryStrategie(code) from anywhere.
Instead of implicitly implementing the factory inside main, keep the whole factory code separate, to make it easily maintainable and extensible .

Related

What is a good design to execute the methods based on boolean values in Database in Java?

We have few rules, which are Implemented as methods in Java. But sometimes we need to bypass the rules. So for each rule, we have a boolean Indicator to indicate whether to execute or not. What can be a good design to map the methods to boolean values in Database and execute methods based on the boolean values.
Below is sample template
1 Rule1 true
2 Rule2 false
3 Rule3 true
4 Rule4 true
So, now I need to execute method1(), method3() and method4() respectively.
One Simple way can be using If(rulee == true) executeMethod();
Second is using a Switch to execute the cases (method calls)
Note: We may need to execute the methods in different locations(methods). So please dont consider that all the methods will be called from a single method.
Can I make use of AOP by any chance?
You could define the basic interface as
public interface Rule {
boolean canExecute();
void execute();
}
and convert the methods into Rule interface implementations. The boolean value in the database would map to canExecute() return value.
This would be a good idea if methods are becoming complex, there's more than a few of them and the parent class is starting to look like a God Object.
Use Java 8 Stream api and Enums.
public class Main {
public enum Rule {
RULE1 {
#Override
public void doWork() {
}
},
RULE2 {
#Override
public void doWork() {
}
};
public abstract void doWork();
}
public static void main(String[] args) {
List<String> rules = new ArrayList<>();
rules.stream()
.map(Rule::valueOf)
.forEach(Rule::doWork);
}
}
You can just call all methods and do the validation part within the method implementation, e.g.:
void rule1(Object... args){
if (!applyRule1){
return;
}
...
}
With that approach, you can reduce cyclomatic complexity and prevent tools such as PMD from complaining.
Another approach is to store the method names as strings in the database. If your database supports arrays, that's particularly easy.
Then in Java you can set up an executor that accepts a String name and execute the respective rule:
import java.util.List;
import static java.util.Arrays.asList;
public class ByNameExecutor {
enum Rule {
Rule1 { #Override void rule() { System.out.println("Executed rule 1"); } },
Rule2 { #Override void rule() { System.out.println("Executed rule 2"); } },
Rule3 { #Override void rule() { System.out.println("Executed rule 3"); } },
Rule4 { #Override void rule() { System.out.println("Executed rule 4"); } },
;
abstract void rule();
}
public void execute(String ruleName) {
Rule.valueOf(ruleName).rule();
}
public void execute(List<String> ruleNames) {
ruleNames.stream().forEach(this::execute);
}
public static void main(String [] args) {
String [] methodList = { "Rule1", "Rule2", "Rule4" };
new ByNameExecutor().execute(asList(methodList));
}
}
An advantage of this approach is that you don't need to change the database schema to add a rule. Just start storing the new rule's string name. A disadvantage is that if you need to query on presence of or absence of a given rule, the database must support indexes over arrays.
Update: I replaced Consumer interface with Runnable in my original answer, because it aligns with example in the question better.
You can try to upgrade your Rule entity, here is an idea using Runnable interface:
class Rule {
private boolean isActive;
private Runnable runnable;
public Rule(boolean isActive, Runnable runnable) {
this.isActive = isActive;
this.runnable = runnable;
}
public void executeIfActive() {
if (isActive) {
runnable.run();
isActive = false;
}
}
}
Example of the use:
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
List<Rule> rules = List.of(new Rule(true, demo::m1), new Rule(false, demo::m2));
rules.forEach(Rule::executeIfActive);
}
void m1() { ... }
void m2() { ... }
}
demo::m1 is a method reference that would invoke the method demo.m1(), and the same for m2.
If I understand the problem correctly then it should work. You can have a method like below and call it from anywhere.
Or these booleans can also be a rule and you can add multiple methods in one IF condition
void executeMethods(boolean m1, boolean m2, boolean m3, boolean m4){
if(m1) m1();
if(m2) m2();
if(m3) m3();
if(m4) m4();
}
executeMethods(true,false,false,true);
Instead of store Boolean you can store method names in this field accordingly. Then all you need to do would be invoke that method using reflection.
Table:
Id RULE_NAME METHOD_NAME
1 Rule1 method1
2 Rule2
3 Rule3 method3
4 Rule4 method4
The method can be invoked like this:
ResultSet srs = stmt.executeQuery("SELECT METHOD_NAME from table");
while (srs.next()) {
String methodName = srs.getString("METHOD_NAME");
if (!TextUtils.isEmpty(methodName)) {
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod(methodName, parameterTypes); // method name will be fetched from Database
method.invoke(objectToInvokeOn, params);
}
}
Reflection API > Invoking Methods
Lets solve this problem with a database driven approach, and Spring AOP.
You have several hundred rules, and do not wish to pollute the current code with boilerplate code like void method1() { if (!rule1) return; .. do method } or have to create additional interfaces which all rule based methods must implement.
Spring AOP provides a means to leave the current base in tact, and instead have methods intercepted (via a proxy) to determine if the method should run or not. You write the proxy code once, and the only ongoing requirement is to keep the database up to date with new rules.
Step 1: Build a database schema which maps method names to boolean values
method_name VARCHAR(100), is_rule_active tinyint(1);
There will be one row for each rule. The row will contain the method name (as it appears in the java code) and a boolean true=active, false=not active.
Step 2: Build an interface to the database (DAO)
You need a simple abstraction to the database. Something like:
public interface RuleSelectionInterface {
boolean isRuleActive(String methodName);
}
The implementation will be basic DAO code, which will query for the row with method_name equal to methodName. For simplicity, and to demonstrate, I used a Map instead:
#Repository
public class RuleSelectionImpl implements RuleSelectionInterface {
Map<String, Boolean> rules;
public RuleSelectionImpl() {
rules = new HashMap<>();
rules.put("rule1Method", true);
rules.put("rule2Method", false);
}
#Override
public boolean isRuleActive(String methodName) {
if (!rules.containsKey(methodName))
return false;
return rules.get(methodName);
}
}
Step 3: Create a Spring AOP aspect
An aspect is created to intercept method calls, and determine when the call should be executed.
To allow execution to be continued, or aborted, you use an #Around advice, which will be passed the execution point (by means of a ProceedingJoinPoint) from which you can either abort (the proxy method simply returns) or run the code by using the proceed method.
There is some choice here on which methods should be intercepted (this is done by defining pointcuts). This example will intercept methods with names starting with rule:
#Around("execution(* rule*(..))")
You could intercept all methods, or methods based on naming patterns, etc. For a detailed understanding of how to create pointcuts to intercept methods refer to Spring AOP
Here is the AOP code, which is called upon method interception, and which uses your database rule interface to look up if the rule is active for this method name:
#Aspect
#Component
public class RuleAspects {
#Autowired
private RuleSelectionInterface rulesSelectionService;
#Around("execution(* rule*(..))")
public void ruleChooser(ProceedingJoinPoint jp) throws Throwable
{
Signature sig = jp.getSignature();
System.out.println("Join point signature = "+sig);
String methodName = sig.getName();
if (rulesSelectionService.isRuleActive(methodName))
jp.proceed();
else
System.out.println("Method was aborted (rule is false)");
}
}
Sample usage:
I created a simple class with two methods (however this approach works regardless of how many classes/methods you have rule based methods for).
#Component
public class MethodsForRules {
public void rule1Method() {
System.out.println("Rule 1 method");
}
public void rule2Method() {
System.out.println("Rule 2 method");
}
}
You will have noticed in the Map that rule1Method is set to true, and rule2Method is set to false.
When the code tries to run rule1Method and rule2Method:
MethodsForRules r; // Is a Spring managed bean.
r.rule1Method();
r.rule2Method();
Produces the following output:
Join point signature = void com.stackoverflow.aoparound.demo.MethodsForRules.rule1Method()
Rule 1 method <- Here is the method running
Join point signature = void
com.stackoverflow.aoparound.demo.MethodsForRules.rule2Method()
Method was aborted (rule is false) <- Here the method is aborted
Summary:
This demonstration has shown how Spring AOP can be used, in combination with a rules based interface, to intercept methods (by using a proxy), examine the method name which was intercepted, lookup the active status for this method, and either run the method, or abort it.

How eliminate switch in this specific example

I have controller method that get data from request and based on subject variable from request decide to call a function. (for project need I cannot use seperate controller method for each subject variable)
For now I used switch but I think it breaks Open Closed Principle (because every time new type of subject added I have to add new case to switch) and not good design, How can I refactor this code?
Subject subject = ... //(type of enum)
JSONObject data = request.getData("data");
switch(subject) {
case SEND_VERIFY:
send_foo1(data.getString("foo1_1"), data.getString("foo1_2"));
break;
case do_foo2:
foo2(data.getInt("foo2_b"), data.getInt("foo2_cc"));
break;
case do_foo3:
do_foo3_for(data.getString("foo3"));
break;
// some more cases
}
While I am not sure about which OO principle this snippet violates, there is indeed a more roust way to achieve the logic: tie the processing for each enum value to the enum class.
You will need to generalize the processing into an interface:
public interface SubjectProcessor
{
void process(JSONObject data);
}
and create concrete implementations for each enum value:
public class SendVerifySubjectProcessor implements SubjectProcessor
{
#Override
public void process(JSONObject data) {
String foo1 = data.getString("foo1_1");
String foo2 = data.getString("foo1_2");
...
}
}
once you have that class hierarchy tree, you can associate each enum value to a concrete processor
public enum Subject
{
SEND_VERIFY(new SendVerifySubjectProcessor()),
do_foo2(new Foo2SubjectProcessor()),
...
private SubjectProcessor processor
Subject(SubjectProcessor processor) {
this.processor = processor;
}
public void process(JSONObject data) {
this.processor.process(data);
}
}
This eliminates the need for the switch statement in the controller:
Subject subject = ... //(type of enum)
JSONObject data = request.getData("data");
subject.process(data);
EDIT:
Following the good comment, You can utilize the java.util.function.Consumer functional interface instead of the custom SubjectProcessor one. You can decide whether to write concrete classes or use the lambda expr construct.
public class SendVerifySubjectProcessor implements Consumer<JSONObject>
{
#Override
public void accept(JSONObject data) {
String foo1 = data.getString("foo1_1");
String foo2 = data.getString("foo1_2");
...
}
}
OR
public enum Subject
{
SEND_VERIFY(data -> {
String foo1 = data.getString("foo1_1");
String foo2 = data.getString("foo1_2");
...
}),
...
private Consumer<Subject> processor
Subject(Consumer<Subject> processor) {
this.processor = processor;
}
public void process(JSONObject data) {
this.processor.accept(data);
}
}
// SubjectsMapping.java
Map<Subject, Consumer<JSONObject>> tasks = new HashMap<>();
tasks.put(SEND_VERIFY,
data -> send_foo1(data.getString("foo1_1"), data.getString("foo1_2")));
tasks.put(do_foo2,
data -> foo2(data.getInt("foo2_b"), data.getInt("foo2_cc")));
tasks.put(do_foo3, data -> do_foo3_for(data.getString("foo3")));
// In your controller class where currently `switch` code written
if (tasks.containsKey(subject)) {
tasks.get(subject).accept(data);
} else {
throw new IllegalArgumentException("No suitable task");
}
You can maintain Map<Subject, Consumer<JSONObject>> tasks configuration in separate class rather than mixing with if (tasks.containsKey(subject)) code. When you need another feature you can configure one entry in this map.
Answers of others seems to be great, as an addition I would suggest using EnumMap for storing enums as keys as it might be more efficient than the standard Map. I think it's also worth mentioning that the Strategy Pattern is used here to achieve calling specific actions for each key from Map without the need of building long switch statements.

How to improve the code quality to see if a string matches either one of the regex's Java

In one of my projects I need to compare the URI with several regex patterns(15+ regex patterns). Currently I have used a if ladder to see if either one of them gets matched and there onward the logical part of the code is executed.
Glimpse of the code now:
if (uri.matches(Constants.GET_ALL_APIS_STORE_REGEX)) {
long lastUpdatedTime = InBoundETagManager.apisGet(null, null, tenantDomain, null);
String eTag = ETagGenerator.getETag(lastUpdatedTime);
if (eTag.equals(ifNoneMatch)) {
message.getExchange().put("ETag", eTag);
generate304NotModifiedResponse(message);
}
message.getExchange().put("ETag", eTag);
}
else if (uri.matches(Constants.GET_API_FOR_ID_REGEX)) { // /apis/{apiId}
apiId = UUIDList.get(0);
String requestedTenantDomain = RestApiUtil.getRequestedTenantDomain(tenantDomain);
long lastUpdatedTime = InBoundETagManager.apisApiIdGet(apiId, requestedTenantDomain, uri);
String eTag = ETagGenerator.getETag(lastUpdatedTime);
handleInterceptorResponse(message, ifNoneMatch, eTag);
}
else if (uri.matches(Constants.GET_SWAGGER_FOR_API_ID_REGEX)) { // /apis/{apiId}/swagger
apiId = UUIDList.get(0);
long lastUpdatedTime = InBoundETagManager.apisApiIdSwaggerGet(apiId, tenantDomain);
String eTag = ETagGenerator.getETag(lastUpdatedTime);
if (lastUpdatedTime == 0L) {
log.info("No last updated time available for the desired API swagger json file");
}
handleInterceptorResponse(message, ifNoneMatch, eTag);
}
Can someone please introduce me with a more neat and clever way of doing this regex matching thing?
One url-type(regex) = one handler = one class. This way would be much easier to read and support especially if you have 15 regex checks.
interface URLHandler {
void handle();
boolean isSupported(String url);
}
class GetAllApisStoreHandler implements URLHandler{
private static final Pattern GET_ALL_API_STORE_PATTERN = Pattern.compile(GET_ALL_APIS_STORE_REGEX);
public boolean isSupported(String url) {
return GET_ALL_API_STORE_PATTERN.matcher(url).matches();
}
public void handle(...) {
...
}
}
class GetApiIdHandler implements URLHandler{
private static final Pattern GET_API_ID_REGEX = Pattern.compile(GET_API_ID_REGEX);
public boolean isSupported(String url) {
return GET_API_ID_PATTERN.matcher(url).matches();
}
public void handle(...) {
...
}
}
class GetApiIdHandler implements URLHandler{
private static final Pattern GET_SWAGGER_FORAPI_ID_PATTERN = Pattern.compile(GET_SWAGGER_FOR_API_ID_REGEX);
public boolean isSupported(String url) {
return GET_SWAGGER_FORAPI_ID_PATTERN.matcher(url).matches();
}
public void handle(...) {
...
}
}
class Main {
private List<URLHandler> urlHandlers;
public void method(){
...
for (URLHandler handler : urlHandlers) {
if(handler.isSupported(url)) {
handler.handle(arg1, arg2, arg3, ...);
}
}
...
}
}
Using multiple classes as #KonstantinLabun proposed is probably the way to go(*), but it shouldn't lead to much code duplication. So use an abstract class instead of (or in addition to an interface). Or (mis)use default methods.
abstract class URLHandler {
abstract void handle();
abstract Pattern urlPattern():
final boolean isSupported(String url) {
return urlPattern().matcher(url).matches();
}
}
class GetAllApisStoreHandler extends URLHandler{
private static final Pattern URL_PATTERN =
Pattern.compile(Constants.GET_ALL_APIS_STORE_REGEX);
Pattern urlPattern() {
return URL_PATTERN;
}
public void handle(...) {
...
}
}
There's no need to invent names for the PATTERN as its scope identified it already. The static field exists only as an optimization, so that the Pattern don't get compiled for each match.
(*) There's nothing wrong with a single class, as long as it's concise (I like spaghetti except in code) and doesn't leak implementation details. There's nothing wrong with multiple classes (except maybe on Android as 50 kB per class might matter) as long as they don't lead to code bloat. An enum is sometimes a good solution, too.
Explanation of abstract class vs. interface
An interface forces you to implement its methods(**), which may quickly lead to duplication. It's advantage is multiple inheritance and some conceptual purity.
An abstract class allows you to gather the common parts. But there's no dilemma, you can do both, see e.g., interface List and abstract class AbstractList.
(**) Since Java 8, an interface can have default methods, so this is no more true. Assuming you want to use them for this purpose. It can't declare any state, but it can access the state of the object. For example, my above URLHandler could be such an interface. There are still disadvantages, e.g., methods must be public and mustn't be final.

"if" statement vs OO Design

I have enum say ErrorCodes that
public enum ErrorCodes {
INVALID_LOGIN(100),
INVALID_PASSWORD(101),
SESSION_EXPIRED(102) ...;
private int errorCode;
private ErrorCodes(int error){
this.errorCode = error;
} //setter and getter and other codes
}
now I check my exception error codes with this error codes. I don't want to write if this do this, if this do this. How I can solve this problem (writing 10+ if blocks)
Is there any design patter to that situation ?
Thanks
Either you do it with a if-statement or a switch, or you just implement the logic in question into the ErrorCode somehow.
In an OO fashion it all depends on how you want the application or system react to the error code. Lets say you just want it to output somekind of dialog:
public doSomethingWithError() {
ErrorCodes e = getError();
// the source of error, or originator, returns the enum
switch(e) {
case ErrorCodes.INVALID_LOGIN:
prompt('Invalid Login');
case ErrorCodes.INVALID_PASSWORD:
prompt('Invalid password');
// and so on
}
}
We could instead create an ErrorHandler class that does this instead:
// We'll implement this using OO instead
public doSomethingWithError() {
ErrorHandler e = getError();
// the originator now returns an ErrorHandler object instead
e.handleMessage();
}
// We will need the following abstract class:
public abstract class ErrorHandler {
// Lets say we have a prompter class that prompts the message
private Prompter prompter = new Prompter();
public final void handleMessage() {
String message = this.getMessage();
prompter.prompt(message);
}
// This needs to be implemented in subclasses because
// handleMessage() method is using it.
public abstract String getMessage();
}
// And you'll have the following implementations, e.g.
// for invalid logins:
public final class InvalidLoginHandler() {
public final String getMessage() {
return "Invalid login";
}
}
// E.g. for invalid password:
public final class InvalidPasswordHandler() {
public final String getMessage() {
return "Invalid password";
}
}
The former solution is easy to implement, but becomes difficult to maintain as the code grows larger. The latter solution is more complex, (aka. Template Method pattern following the Open-Closed Principle) but enables you to add more methods into the ErrorHandler when you need it (such as restoring resources or whatever). You can also implement this with the Strategy pattern.
You won't get away completely with the conditional statements, but in the latter the conditional is pushed to the part of the code where the error is originated. That way you won't have double maintenance on conditional statements both at the originator and the error handling code.
EDIT:
See this answer by Michael Borgwardt and this answer by oksayt for how to implement methods on Java Enums if you want to do that instead.
Java enums are very powerful and allow per-instance method implementations:
public enum ErrorCode {
INVALID_LOGIN {
public void handleError() {
// do something
}
},
INVALID_PASSWORD {
public void handleError() {
// do something else
}
},
SESSION_EXPIRED {
public void handleError() {
// do something else again
}
};
public abstract void handleError();
}
Then you can simply call errorCode.handleError();. However, it is questionable whether an ErrorCode enum is really the right place for that logic.
As pointed out by Spoike, using polymorphism to pick the right error handling method is an option. This approach basically defers the 10+ if blocks to the JVM's virtual method lookup, by defining a class hierarchy.
But before going for a full-blown class hierarchy, also consider using enum methods. This option works well if what you plan to do in each case is fairly similar.
For example, if you want to return a different error message for each ErrorCode, you can simply do this:
// Note singular name for enum
public enum ErrorCode {
INVALID_LOGIN(100, "Your login is invalid"),
INVALID_PASSWORD(101, "Your password is invalid"),
SESSION_EXPIRED(102, "Your session has expired");
private final int code;
private final String
private ErrorCode(int code, String message){
this.code = code;
this.message = message;
}
public String getMessage() {
return message;
}
}
Then your error handling code becomes just:
ErrorCode errorCode = getErrorCode();
prompt(errorCode.getMessage());
One drawback of this approach is that if you want to add additional cases, you'll need to modify the enum itself, whereas with a class hierarchy you can add new cases without modifying existing code.
I believe the best you can do is implementing the strategy pattern. This way you won't have to change existing classes when adding new enums but will still be able to extend them. (Open-Closed-Principle).
Search for Strategy Pattern and Open Closed Principle.
You can create a map of error codes(Integer) against enum types
Edit
In this solution, once the map is prepared, you can look up an error code in the map and thus will not require if..else look ups.
E.g.
Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>();
for (ErrorCodes error : ErrorCodes.values()) {
errorMap.put(error.getCode(), error);
}
Now when you want to check an error code coming from your aplpication, all you need to do is,
ErrorCodes error = errorMap.get(erro_code_from_application);
Thus removing the need for all the if..else.
You just need to set up the map in a way that adding error codes doesn't require changes in other code. Preparation of the map is one time activity and can be linked to a database, property file etc during the initialization of your application
In my opinion there is nothing wrong with ErrorCodes as enums and a switch statement to dispatch error handling. Enums and switch fit together really well.
However, maybe you find the following insteresting (kind of over-design), see an Example
or "Double dispatching" on Wikipedia.
Assumed requirements:
Error-handling should be encapsulated in an own class
Error-handling should be replacable
Type safety: Whenever an error is added, you are forced to add error handling at each error-handler implementation. It is not possible to "forget" an error in one (of maybe many) switch statments.
The code:
//Inteface for type-safe error handler
interface ErrorHandler {
void handleInvalidLoginError(InvalidLoginError error);
void handleInvalidPasswordError(InvalidLoginError error);
//One method must be added for each kind error. No chance to "forget" one.
}
//The error hierachy
public class AbstractError(Exception) {
private int code;
abstract public void handle(ErrorHandler);
}
public class InvalidLoginError(AbstractError) {
private String additionalStuff;
public void handle(ErrorHandler handler) {
handler.handleInvalidLoginError(this);
}
public String getAdditionalStuff();
}
public class InvalidPasswordError(AbstractError) {
private int code;
public void handle(ErrorHandler handler) {
handler.handleInvalidPasswordError(this);
}
}
//Test class
public class Test {
public void test() {
//Create an error handler instance.
ErrorHandler handler = new LoggingErrorHandler();
try {
doSomething();//throws AbstractError
}
catch (AbstractError e) {
e.handle(handler);
}
}
}

fuzzy implementation for capturing specific strings

I am going to develop a web crawler using java to capture hotel room prices from hotel websites.
In this case I want to capture room price with the room type and the meal type, so my algorithm should be intelligent to handle that.
For example:
Room type: Deluxe
Meal type: HalfBoad
price : $20.00
The main problem is room prices can be in different ways in different hotel sites. So my algorithm should be independent from hotel sites.
I am plan to use above room types and meal types as a fuzzy sets and compare the words in webpage with above fuzzy sets using a suitable membership function.
Anyone experienced with this? or have an idea for my problem?
There are two ways to approach this problem:
You can customize your crawler to understand the formats used by different Websites; or
You can come up with a general ("fuzzy") solution.
(1) will, by far, be the easiest. Ideally you want to create some tools that make this easier so you can create a filter for any new site in minimal time. IMHO your time will be best spent with this approach.
(2) has lots of problems. Firstly it will be unreliable. You will come across formats you don't understand or (worse) get wrong. Second, it will require a substantial amount of development to get something working. This is the sort of thing you use when you're dealing with thousands or millions of sites.
With hundreds of sites you will get better and more predictable results with (1).
As with all problems, design can let you deliver value adapt to situations you haven't considered much more quickly than the general solution.
Start by writing something that parses the data from one provider - the one with the simplest format to handle. Find a way to adapt that handler into your crawler. Be sure to encapsulate construction - you should always do this anyway...
public class RoomTypeExtractor
{
private RoomTypeExtractor() { }
public static RoomTypeExtractor GetInstance()
{
return new RoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
The GetInstance() ,ethod lets you promote to a Strategy pattern for practically free.
Then add your second provider type. Say, for instance, that you have a slightly more complex data format which is a little more prevalent than the first format. Start by refactoring what was your concrete room type extractor class into an abstraction with a single variation behind it and have the GetInstance() method return an instance of the concrete type:
public abstract class RoomTypeExtractor
{
public static RoomTypeExtractor GetInstance()
{
return SimpleRoomTypeExtractor.GetInstance();
}
public abstract string GetRoomType(string content);
}
public final class SimpleRoomTypeExtractor extends RoomTypeExtractor
{
private SimpleRoomTypeExtractor() { }
public static SimpleRoomTypeExtractor GetInstance()
{
return new SimpleRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// BEHAVIOR #1
}
}
Create another variation that implements the Null Object pattern...
public class NullRoomTypeExtractor extends RoomTypeExtractor
{
private NullRoomTypeExtractor() { }
public static NullRoomTypeExtractor GetInstance()
{
return new NullRoomTypeExtractor();
}
public string GetRoomType(string content)
{
// whatever "no content" behavior you want... I chose returning null
return null;
}
}
Add a base class that will make it easier to work with the Chain of Responsibility pattern that is in this problem:
public abstract class ChainLinkRoomTypeExtractor extends RoomTypeExtractor
{
private final RoomTypeExtractor next_;
protected ChainLinkRoomTypeExtractor(RoomTypeExtractor next)
{
next_ = next;
}
public final string GetRoomType(string content)
{
if (CanHandleContent(content))
{
return GetRoomTypeFromUnderstoodFormat(content);
}
else
{
return next_.GetRoomType(content);
}
}
protected abstract bool CanHandleContent(string content);
protected abstract string GetRoomTypeFromUnderstoodFormat(string content);
}
Now, refactor the original implementation to have a base class that joins it into a Chain of Responsibility...
public final class SimpleRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private SimpleRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static SimpleRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new SimpleRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// return whether or not content contains the right format
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #1
}
}
Be sure to update RoomTypeExtractor.GetInstance():
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
Once that's done, create a new link for the Chain of Responsibility...
public final class MoreComplexRoomTypeExtractor extends ChainLinkRoomTypeExtractor
{
private MoreComplexRoomTypeExtractor(RoomTypeExtractor next)
{
super(next);
}
public static MoreComplexRoomTypeExtractor GetInstance(RoomTypeExtractor next)
{
return new MoreComplexRoomTypeExtractor(next);
}
protected string CanHandleContent(string content)
{
// Check for presence of format #2
}
protected string GetRoomTypeFromUnderstoodFormat(string content)
{
// BEHAVIOR #2
}
}
Finally, add the new link to the chain, if this is a more common format, you might want to give it higher priority by putting it higher in the chain (the real forces that govern the order of the chain will become apparent when you do this):
public static RoomTypeExtractor GetInstance()
{
RoomTypeExtractor extractor = NullRoomTypeExtractor.GetInstance();
extractor = SimpleRoomTypeExtractor.GetInstance(extractor);
extractor = MoreComplexRoomTypeExtractor.GetInstance(extractor);
return extractor;
}
As time passes, you may want to add ways to dynamically add new links to the Chain of Responsibility, as pointed out by Cletus, but the fundamental principle here is Emergent Design. Start with high quality. Keep quality high. Drive with tests. Do those three things and you will be able to use the fuzzy logic engine between your ears to overcome almost any problem...
EDIT
Translated to Java. Hope I did that right; I'm a little rusty.

Categories