I have a use case where there will be 3 kind of data
Business_Enrollment_Program (lets denote them with BEP_1, BEP_2 ...)
Validation_Rule (lets denote them with R1, R2 ...)
Transaction_Type (lets denote them TT_1, TT_2 ...). This is an entity class having some attributes. On these entities Validation_Rule need to be executed.
Transaction_Type entities will look something like
public TT_1 {
private Business_Enrollment_Program;
private COMMON_FIELD_1;
private COMMON_FIELD_2;
private TT_1_SPECIFIC_FIELD;
}
public TT_2 {
private Business_Enrollment_Program;
private COMMON_FIELD_1;
private COMMON_FIELD_2;
private TT_2_SPECIFIC_FIELD;
}
Now i have 2 requirement while executing Validation rules:
Set of Validation_Rule that need to be executed depends on the Transaction_Type and it's Business_Enrollment_Program.
That means for TT_1 enrolled under BEP_1 we might need to execute (R1,R2) rules but for TT_1 enrolled under BEP_2 we might need to execute (R1,R3) rules.
Behavior of rule will depend on Transaction_Type and it's Business_Enrollment_Program. That means for TT_1 enrolled under BEP_1 behavior of rule R1 might be different compared to TT_1 enrolled under BEP_2
For rules i can create a structure like below:
public interface Rule <T> {
public boolean execute(T transactionType);
}
public class R1_For_TT_1 implements Rule<TT_1> {
public boolean execute(TT_1 transactionType) {
//Do something here
}
}
public class R1_For_TT_2 implements Rule<TT_2> {
public boolean execute(TT_2 transactionType) {
//Do something here
}
}
And i can execute the rules like below
public processTransaction(T transactioType) {
private boolean result = true;
if(t instanceof TT_1) {
result = result && R1_For_TT_1.execute(t);
}
else if (t instanceof TT_2) {
result = result && R1_For_TT_1.execute(t);
result = result && R2_For_TT_1.execute(t);
}
if(result) {
// Do something
}
else {
// Do something else
}
}
Issue with this approach is i am not meeting my 2nd requirement where i wanted behavior of rule to depend on Transaction_Type and it's Business_Enrollment_Program.
Any idea how can i arrange my classes and entities so that both of my requirements are fulfilled elegantly?
I would give every BusinessEnrollmentProgram a Map<TransactionType, List<Rule>> as a field, so that you can organize what Rule objects go with each TransactionType. It will make it easy to lookup which Rules need to be executed.
So it would look something like this:
BusinessEnrollmentProgram.java
public class BusinessEnrollmentProgram {
private Map<TransactionType, List<Rule>> transactions = new HashMap<>();
public void processTransaction(TransactionType t) {
List<Rule> rules = transactions.get(t);
boolean result = true;
for (Rule rule : rules) {
if (!rule.execute(t)) {
result = false;
break;
}
}
if (result) {
// do something
} else {
// do something else
}
}
}
TransactionType.java
public class TransactionType {
private COMMON_FIELD_1;
private COMMON_FIELD_2;
// override hashCode() & equals() here so it can be used as a HashMap key
}
Then make all of your transaction types extend TransactionType, and allow your Map to store all of the relationships for which Rule is aloud with which TransactionType. Each BusinessEnrollmentProgram should have a separate set of rules to draw from.
If you're finding that there are too many classes extending Rule, use anonymous classes or lambda expressions instead.
Related
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).
I have entity in database, say, MonthPlan:
class MonthPlan {
private boolean approved;
// other fields
}
There is also REST interface, which accepts external requests based on which program changes entity instances. For example, request
class EditMonthPlanRequest {
private long amount;
// other fields
}
is used to change month plan amount.
What I need is to execute different actions on MonthPlan entity based on value of approved field. For example, code for mentioned request could be as following
MonthPlan plan = getPlan(...);
if (plan.isApproved()) {
// actions using data from EditMonthPlanRequest
} else {
// other actions using data from EditMonthPlanRequest
}
There would be 5-6 different requests each with exactly two variants of actions based on value of approved field of edited entity. What OOP design pattern can I use for such use case to write more concise code?
I do not think you need a design pattern in such a simple case. Each request will be processed by the corresponding method at Service layer.
In this scenario, the state pattern is more suitable.
State design pattern is used when an Object changes its behavior based on its internal state.
If we have to change behavior of an object based on its state, we can have a state variable in the Object and use if-else condition block to perform different actions based on the state. State pattern is used to provide a systematic and lose-coupled way to achieve this through Context and State implementations.
Try to implement based on your description:
public class StatePattern {
public static void main(String[] args) {
MonthPlan monthPlan = null; //= new MonthPlan(...)
StateContext stateContext = new StateContext();
if(monthPlan.isApproved()) {
stateContext.setState(new Approved());
}else {
stateContext.setState(new NotApproved());
}
}
}
class MonthPlan {
private boolean approved;
public boolean isApproved() {
return approved;
}
// other fields
}
interface State{
public void doAction(StateContext ctx);
}
class StateContext{
private State currentState;
public StateContext() {
//default Approved state, you can change if you want
currentState = new Approved();
}
public void setState(State state) {
currentState = state;
}
public void doAction() {
currentState.doAction(this);
}
}
class Approved implements State{
#Override
public void doAction(StateContext ctx) {
//actions using data from EditMonthPlanRequest
}
}
class NotApproved implements State{
#Override
public void doAction(StateContext ctx) {
//other actions using data from EditMonthPlanRequest
}
}
For this simple case, the Template Method pattern may apply:
abstract class AbstractRequest {
public void execute(...){
MonthPlan plan = getPlan(...);
if (plan.isApproved()) {
executeForApproved(plan);
} else {
executeForNonApproved(plan);
}
}
protected abstract void executeForApproved(MonthPlan plan);
protected abstract void executeForNonApproved(MonthPlan plan);
}
This way, you don't need to repeat the if statement and the getPlan(...) in each subclass:
class EditMonthPlanRequest extends AbstractRequest {
private long amount;
// other fields
protected void executeForApproved(MonthPlan plan){
...
}
protected void executeForNonApproved(MonthPlan plan){
...
}
}
If you want to do OOP, then replace conditionals with polymorphism.
In this example, it means splitting MonthPlan in two.
class ApprovedMonthPlan extends MonthPlan
class UnapprovedMonthPlan extends MonthPlan
Each class handles EditMonthPlanRequest in its own way.
I know my question title is not relevant to what I'm asking, but not getting any better title. But feel free to suggest title. (So it will be helpful for others as well)
Here is the scenario I'm having:
I've enum class as below
public enum CalendarBasis {
FISCAL_YEAR,
CALENDAR
}
This enum is used in multiple objects in project.
I want to know the best practice/design pattern to follow which will be helpful for having functionality based on value of enum. Today there are only two values in CalendarBasis but tomorrow there can be multiple values.
This is what I'm doing currently:
Consider I've Object SpecificElement which has CalendarBasis enum parameter.
public class SpecificElement {
private SpecificValue specificValue; //some object
// few more Objects defined
private CalendarBasis calendarBasis;
//getters & setters
}
Following function do some operations on SpecificElement based on type of calendarBasis.
public Foo doCalculations(SpecificElement specificElement)
{
if(specificElement.getCalendarBasis().equals(CalendarBasis.FISCAL_YEAR)){
//do something based on fiscal & return.
}
if(specificElement.getCalendarBasis().equals(CalendarBasis.CALENDAR)){
//do something based on CALENDAR & return.
}
}
I want to know if I can have something like multiple class Implementations based on Enum values & do operations related to that enum inside implementation class.
There are around 8-10 different functions as doCalculations which has business logic based on enum type.
The code structure I'm following doesn't seems to be good practice.
So it will be helpful if someone can give me light on structuring this kind of scenario.
To give a concrete example of Siddarth Sreeni's answer
You create an interface:
public interface Calculations {
Foo doCalculations(SpecificElement element);
}
Then you have your enum implement the interface:
public enum CalendarBasis implements Calculations {
FISCAL_YEAR {
#Override
public Foo doCalculations(SpecificElement element) {
return new OtherFoo();
}
},
CALENDAR {
#Override
public Foo doCalculations(SpecificElement element) {
return new Foo();
}
}
}
Your main doCalculations method would then look like:
public Foo doCalculations(SpecificElement specificElement) {
return specificElement.getCalendarBasis().doCalculations(specificElement);
}
I think you can use EnumMap. If your strategies are stateless (as appears to be the case in your examples), then you simply initialize a map with all of your strategies and use StrategyType to retrieve the one you want.
enum CalendarBasisStrategyType { FISCAL_YEAR, CALENDAR }
static EnumMap<CalendarBasisStrategyType, CalendarBasisStrategy> lookupStrategy = new EnumMap();
{
lookupStrategy.put(FISCAL_YEAR, new FiscalYearStrategyObject());
lookupStrategy.put(CALENDAR, new CalenderBasisStrategyObject());
}
CalendarBasisStrategy toStrategy(CalendarBasisStrategyType type) {
return lookupStrategy.get(type);
}
If it is not stateless then you can use Factory for Creating Objects.
enum CalendarBasisStrategyType { FISCAL_YEAR, CALENDAR }
static EnumMap<CalendarBasisStrategyType, CalendarBasisFactory> lookupFactory = new EnumMap();
{
...
}
CalendarBasisStrategy toStrategy(CalendarBasisStrategyType type) {
return lookupFactory.get(type).newInstance();
}
I would strongly consider using the Strategy pattern for this. This should help to keep your code clean and maintainable, by separating different calculations into their own classes. You can use a Factory to get the right type of calculation.
public enum CalendarBasis {
FISCAL_YEAR,
CALENDAR
}
public interface Calculation {
double performCalculation();
}
public class FiscalCalculation implements Calculation {
#Override
public double performCalculation() {
//Perform calculation.
}
}
public class CalendarCalculation implements Calculation {
#Override
public double performCalculation() {
//Perform calculation.
}
}
public class CalculationFactory {
public static Calculation getCalculation(CalendarBasis calendarBasis) {
switch (calendarBasis) {
case CALENDAR: return new CalendarCalculation();
case FISCAL_YEAR: return new FiscalCalculation();
default:
//Should not happen.
throw new IllegalArgumentException("Invalid basis: " + calendarBasis);
}
}
}
//Usage
double result = CalculationFactory.getCalculation(specificObject.getCalendarBasis()).performCalculation();
Lets say we need some logic change in multiple methods of multiple classes on basis of a flag, while keeping backwards compatibility.
There are two ways..
1.overload every method in every class. then end up with an if-else ladder in caller code to call correct method.
2.Make a common interface and a Factory. Return objects of either on basis of flag passed to factory. Callers don't need any change. only a little change is needed while object creation. Is it logical to create factory for two types only ?
Based on your experience which will you choose ? How to decide between these two ways ? Any better approach you can suggest ?
Logic change suggests behavior which suggests the Strategy Pattern. This avoids a change to the existing method signature.
But you can still use a factory to centralize the creation of the concrete strategy object which handles the logic.
import java.util.Random;
public class App {
public static void main(String[] args) {
App app = new App();
app.calculateSomething(new Random().nextBoolean());
}
private void calculateSomething(boolean isUsingLegacyLogic) {
CalculationStrategyFactory factory = new CalculationStrategyFactory();
CalculationStrategy strategy = factory.getCalculationStrategy(isUsingLegacyLogic);
Calculator calculator = new Calculator(strategy);
calculator.calculate();
}
class Calculator {
CalculationStrategy calculationStrategy;
Calculator(CalculationStrategy calculationStrategy) {
this.calculationStrategy = calculationStrategy;
}
// ...
public double calculate() {
// original code
// ...
// System.out.println("Calculation steps were done in sequential order.");
// return 0;
return calculationStrategy.calculate(this);
}
}
private interface CalculationStrategy {
double calculate(Calculator c);
}
private class SequentialCalculationHandler implements CalculationStrategy {
public double calculate(Calculator c) {
// ...
System.out.println("Calculation steps were done in sequential order.");
return 0;
}
}
private class ParallelCalculationHandler implements CalculationStrategy {
public double calculate(Calculator c) {
// ...
System.out.println("Calculation steps were done in parralel.");
return 0;
}
}
private class CalculationStrategyFactory {
public CalculationStrategy getCalculationStrategy(boolean isUsingLegacyLogic) {
if (isUsingLegacyLogic || Runtime.getRuntime().availableProcessors() == 1) {
return new SequentialCalculationHandler();
}
return new ParallelCalculationHandler();
}
}
}
I am working on a component which is supposed to:
receive data (collection of items) from some external calculation component. I expect about 100-1K of items on input on each request.
validate data, calculate some attributes if missing
persist data
There are about ten types of items. I use inheritance to model items. I have a base item class with common attributes and calculations and subclasses implementing type specific problems. Similar to following example:
public abstract class BaseItem {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
}
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
public class ItemA1 extends ItemA {
BigDecimal extraValue;
#Override
public void postCalucate() {
//some A1 subtype specific calculations
valid = isA1ItemValid();
super.postCalucate();
}
}
public class ItemB extends BaseItem {
Integer size;
#Override
public void postCalucate() {
//some B specific calculations
super.postCalucate();
}
}
Is there any better way/pattern to do my task? Any advices?
The pattern you are trying to use is fairly sound. In general, I would probably suggest the use of an interface instead of a BaseItem class, since it might not contain that much common functionality.
In general, most people seem to recommend defining interfaces for your classes to implement. If absolutely you want to share common code in an AbstractClass, I would recommend that class implementing the interface, since this pattern would lend itself to greater extensibility and flexibility in the future.
As such, you would first begin by defining what an Item is for you. For me, it seems that an Item is three things in your use case: one, it must define the postCalculate() method that will be called on all Items. Second, it must provide an isValid() method. And third, it should also provide a getName() method.
public interface Item {
void postCalucate();
boolean isValid();
String getName();
}
Then you would begin implementing your Abstract class. Do this only if it really is necessary to share a codebase between all your items.
public abstract class BaseItem implements Item {
String name;
boolean valid = true;
public void postCalucate() {
//common calculation
valid = valid && (name != null);
}
public boolean isValid() {
return valid;
}
public String getName() {
return name;
}
}
If BaseItem.postCalculate() is something that will need to be done for all items, this is a good way to do it. If you're not entirely sure, it might be a good idea instead to define a method somewhere in a Helper or Tool class that performs this common calculation for items, and is called by the postCalculate() methods:
public class ItemTools {
public static boolean meetsRequirements(Item item) {
return item.isValid && item.getName() != null;
}
}
This, many would argue, gives you an easier time as your requirements on BaseItem may change over time.
Regardless of which route you go there, now you'll just have to define your actual items:
public class ItemA extends BaseItem {
BigDecimal value;
#Override
public void postCalucate() {
//some A specific calculations
super.postCalucate();
}
}
While the general advice is to avoid over-usage of inheritance, this is no case of over-usage. So, go ahead with this approach.
Apart from that: Your code shows problems with encapsulation. You shouldn’t have all these non-private field. As a reminder: no visibility at all is package-visibility (visible in the whole package and to all sub-classes). Make your fields private.
A priori, your proposal seems reasonable.
But to be sure, you have to look at all the events of the life cycle of your objects:
instantiation
use, read
collaboration
persistence
...