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.
Consider the following: say we have an IRestaurant and an IBooking interface.
We then have the following interface function:
interface IBooking {
void reserve(IRestaurant restaurant);
}
However, business requirements dictate a booking service in a country could make reservations to only restaurants in the same country. Then say we have in USA:
class USABooking implements IBooking { ... }
class USARestaurant implements IRestaurant { ... }
In this case, since reserve() in IBooking takes in any instance of IRestaurant, the USABooking implementation would be required to check the instance of the IRestaurant to see if it is an instance of a USARestaurant and then downcast. However, we could also do this as an alternative:
interface IBooking<R extends IRestaurant> {
void reserve(R restaurant);
}
class USABooking implements IBooking<USARestaurant> {
void reserve(USARestaurant restaurant) { ... }
}
Is this a recommended way to go about enforcing the type limitation? In other words, is this better than performing runtime checks on the restaurant instance types? The typing approach sounds good to me, but I just want to make sure it won't "blow up" the architecture and turn out to be a misuse or abuse, since there are other interfaces that also would require such limitations (e.g. ICuisine).
Here's another alternative since I don't understand why there are USABooking and USARestaurant classes:
Consider just having a Booking and Restaurant class, where Restaurant provides a getCountry() method. Separately, to avoid a proliferation of classes, a Booking instance might have something like a List<RestaurantBookingRule> - in this case there would be a single rule that checks the country of the Restaurant. For example:
public class Restaurant {
private final String country; // constructor omitted
public String getCountry() { return country; }
}
public interface RestaurantBookingRule {
public void validateRequest(Restaurant r); // throws exception if the rule is broken
}
public class RequiredCountry implements BookingRule {
private final String country; // constructor omitted
public void validateRequest(Restaurant r) {
if (!r.getCountry().equals(country))
throw ...
}
}
public class Booking {
private final List<RestaurantBookingRule> rules; // constructor omitted
public void reserve(Restaurant r) {
rules.forEach(r -> r.validateRequest(r));
...
}
}
then:
Restaurant r1 = new Restaurant("USA");
Restaurant r2 = new Restaurant("CAN");
Booking usaBooking = new Booking(List.of(new RequriedCountry("USA"));
usaBooking.reserve(r1); // ok
usaBooking.reserve(r2); // throws exception
Premise
Existing codebase (not likely to change):
public interface Shape {
void print();
}
And with the implementations such as (Circle, Triangle, Square, etc):
public final class Circle implements Shape {
private final CircleInput input;
public Circle(CircleInput input) {
this.input = input;
}
#Override
public void print() { ... }
}
CircleInput, TriangleInput, and SquareInput are NOT related at all (disjoint types).
Problem
Input objects can be very complex and I want users to create a class that encapsulates their own business logic. I explored two approaches, but they were both clunky and that leads me to think if I am approaching the problem incorrectly and there is a better way to use Java.
Option 1
I thought about defining a generic interface:
public interface ShapeInput<T> {
T getInput();
}
User can then create:
public final class MyCircleInput<CircleInput> {
private final ShapeDependency shapeDependency;
#Inject
MyCircleInput(ShapeDependency shapeDependency) {
this.shapeDependency = shapeDependency;
}
#Override
public CircleInput getInput() {
return createCircleInput(shapeDependency);
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}
then use a ShapeFactory to create the correct instance based on type. But I am unable to say ShapeInput<CircleInput | TriangleInput> and enforcing this behavior requires runtime checks.
Option 2
I could use inheritance on Shape directly:
public abstract class AbstractShape implements Shape {
protected final Shape shapeImpl;
public AbstractShape(CircleInput input) {
this.shapeImpl = new Circle(input);
}
public AbstractShape(TriangleInput input) {
this.shapeImpl = new Triangle(input);
}
// Proxies print() to the underlying impl.
#Override
public void print() {
return shapeImpl.print();
}
}
and users can create:
public final MyCircle extends AbstractShape {
#Inject
MyCircle(ShapeDependency shapeDependency) {
super(createCircleInput(shapeDependency));
}
// ... very complex business logic ...
private static CircleInput createCircleInput(
ShapeDependency shapeDependency) {
// returns a CircleInput
}
}
So Circle, Square, Triangle (which are all Shapes) and their respective inputs CircleInput, SquareInput, and TriangleInput (which are disjoint) are already well-defined in this system?
Why should the users extend any of these inputs at all?
Isn't your pipeline essentially that a ShapeDependency is acted upon by some business logic to create ShapeInput and pass it to the correct Shape?
You could clarify this by clearly defining the responsibility of each class. I would expect the sole responsibility of CircleInput, SquareInput etc would be to just hold input data, not to perform business logic.
I would keep that business logic in its own class, maybe something like this:
abstract class BusinessLogic<S extends Shape, I> {
private final Function<I, S> shapeConstructor;
public BusinessLogic(Function<I, S> shapeConstructor) {
this.shapeConstructor = shapeConstructor;
}
protected abstract I createShapeInput(ShapeDependency shapeDependency);
public final S createShape(ShapeDependency shapeDependency) {
I shapeInput = createShapeInput(shapeDependency);
S shape = shapeConstructor.apply(shapeInput);
return shape;
}
}
class CircleBusinessLogic extends BusinessLogic<Circle, CircleInput> {
public CircleBusinessLogic() {
super(Circle::new);
}
#Override
protected CircleInput createShapeInput(ShapeDependency shapeDependency) {
return new CircleInput();
}
}
Let me know if this satisfies your requirements. If not, please clarify your goals and pipeline.
I would like to design a class which can (or not) implement functionalities, and be open to add new ones in the future. Those functionalities must be executed by a method. For instance:
class Hero()
doDamage(){
//simpleDamage
}
And
class BetterHero() implements EnableCriticAttack
doDamage(){
//damage with critic attack chance
}
Also,
class WizardBetterHero() implements EnableCriticAttack, MagicDamage
doDamage(){
//damage with critic attack chance + magic damage
}
I would like to add new "special abilities" using the proper design pattern, so doDamage() method will know which abilities to use, and it does properly. I don't want to create different classes, just "add" new functionalities to the created one: open-close principle.
PD: I put the functionalities as interfaces, but it is just an example.
Different ways of inflicting damage is a behavior which suggests using the Strategy design pattern. For example, have a Damage interface such as:
public interface Damage {
public void doDamage();
}
and a few implementations such as:
public class SimpleDamage implements Damage {
public void doDamage() {
System.out.println("simple damage");
}
}
public class MagicDamage implements Damage {
public void doDamage() {
System.out.println("magic damage");
}
}
So then there is only a need for a single Hero type such as:
public class Hero implements Damage {
private final Damage damage;
public Hero(Damage damage) {
this.damage = damage;
}
public void doDamage() {
damage.doDamage();
}
}
Implementations of Damage could also use the Decorator design pattern. For example, a Hero's damage could include mulitple ways to inflict damage:
public class MagicDamage implements Damage {
private final Damage additionalDamage;
public MagicDamage(Damage additionalDamage) {
this.additionalDamage = additionalDamage;
}
public void doDamage() {
if (additionalDamage != null) {
additionalDamage.doDamage();
}
System.out.println("magic damage");
}
}
...
Hero hero = new Hero(new MagicDamage(new SimpleDamage());
This question already has answers here:
When should I use the Visitor Design Pattern? [closed]
(20 answers)
Closed 5 years ago.
I'm really confused about the visitor pattern and its uses. I can't really seem to visualize the benefits of using this pattern or its purpose. If someone could explain with examples if possible that would be great.
So you've probably read a bajillion different explanations of the visitor pattern, and you're probably still saying "but when would you use it!"
Traditionally, visitors are used to implement type-testing without sacrificing type-safety, so long as your types are well-defined up front and known in advance. Let's say we have a few classes as follows:
abstract class Fruit { }
class Orange : Fruit { }
class Apple : Fruit { }
class Banana : Fruit { }
And let's say we create a Fruit[]:
var fruits = new Fruit[]
{ new Orange(), new Apple(), new Banana(),
new Banana(), new Banana(), new Orange() };
I want to partition the list in to three lists, each containing oranges, apples, or bananas. How would you do it? Well, the easy solution would be a type-test:
List<Orange> oranges = new List<Orange>();
List<Apple> apples = new List<Apple>();
List<Banana> bananas = new List<Banana>();
foreach (Fruit fruit in fruits)
{
if (fruit is Orange)
oranges.Add((Orange)fruit);
else if (fruit is Apple)
apples.Add((Apple)fruit);
else if (fruit is Banana)
bananas.Add((Banana)fruit);
}
It works, but there are lots of problems with this code:
For a start, its ugly.
Its not type-safe, we won't catch type errors until runtime.
Its not maintainable. If we add a new derived instance of Fruit, we need to do a global search for every place which performs a fruit type-test, otherwise we might miss types.
Visitor pattern solves the problem elegantly. Start by modifying our base Fruit class:
interface IFruitVisitor
{
void Visit(Orange fruit);
void Visit(Apple fruit);
void Visit(Banana fruit);
}
abstract class Fruit { public abstract void Accept(IFruitVisitor visitor); }
class Orange : Fruit { public override void Accept(IFruitVisitor visitor) { visitor.Visit(this); } }
class Apple : Fruit { public override void Accept(IFruitVisitor visitor) { visitor.Visit(this); } }
class Banana : Fruit { public override void Accept(IFruitVisitor visitor) { visitor.Visit(this); } }
It looks like we're copy pasting code, but note the derived classes are all calling different overloads (the Apple calls Visit(Apple), the Banana calls Visit(Banana), and so on).
Implement the visitor:
class FruitPartitioner : IFruitVisitor
{
public List<Orange> Oranges { get; private set; }
public List<Apple> Apples { get; private set; }
public List<Banana> Bananas { get; private set; }
public FruitPartitioner()
{
Oranges = new List<Orange>();
Apples = new List<Apple>();
Bananas = new List<Banana>();
}
public void Visit(Orange fruit) { Oranges.Add(fruit); }
public void Visit(Apple fruit) { Apples.Add(fruit); }
public void Visit(Banana fruit) { Bananas.Add(fruit); }
}
Now you can partition your fruits without a type-test:
FruitPartitioner partitioner = new FruitPartitioner();
foreach (Fruit fruit in fruits)
{
fruit.Accept(partitioner);
}
Console.WriteLine("Oranges.Count: {0}", partitioner.Oranges.Count);
Console.WriteLine("Apples.Count: {0}", partitioner.Apples.Count);
Console.WriteLine("Bananas.Count: {0}", partitioner.Bananas.Count);
This has the advantages of:
Being relatively clean, easy to read code.
Type-safety, type errors are caught at compile time.
Maintainability. If I add or remove a concrete Fruit class, I could modify my IFruitVisitor interface to handle the type accordingly, and the compiler will immediately find all places where we implement the interface so we can make the appropriate modifications.
With that said, visitors are usually overkill, and they have a tendency to grossly complicate APIs, and it can be very cumbersome to define a new visitor for every new kind of behavior.
Usually, simpler patterns like inheritance should be used in place of visitors. For example, in principle I could write a class like:
class FruitPricer : IFruitVisitor
{
public double Price { get; private set; }
public void Visit(Orange fruit) { Price = 0.69; }
public void Visit(Apple fruit) { Price = 0.89; }
public void Visit(Banana fruit) { Price = 1.11; }
}
It works, but what's the advantage over this trivial modification:
abstract class Fruit
{
public abstract void Accept(IFruitVisitor visitor);
public abstract double Price { get; }
}
So, you should use visitors when the following conditions hold:
You have a well-defined, known set of classes which will be visited.
Operations on said classes are not well-defined or known in advance. For example, if someone is consuming your API and you want to give consumers a way to add new ad-hoc functionality to objects. They're also a convenient way to extend sealed classes with ad-hoc functionaity.
You perform operations of a class of objects and want to avoid run-time type testing. This is usually the case when you traverse a hierarchy of disparate objects having different properties.
Don't use visitors when:
You support operations on a class of objects whose derived types are not known in advance.
Operations on objects are well-defined in advance, particularly if they can be inherited from a base class or defined in an interface.
Its easier for clients to add new functionality to classes using inheritance.
You are traversing a hierarchy of objects which have the same properties or interface.
You want a relatively simple API.
Once upon a time...
class MusicLibrary {
private Set<Music> collection ...
public Set<Music> getPopMusic() { ... }
public Set<Music> getRockMusic() { ... }
public Set<Music> getElectronicaMusic() { ... }
}
Then you realize you'd like to be able to filter the library's collection by other genres. You could keep adding new getter methods. Or you could use Visitors.
interface Visitor<T> {
visit(Set<T> items);
}
interface MusicVisitor extends Visitor<Music>;
class MusicLibrary {
private Set<Music> collection ...
public void accept(MusicVisitor visitor) {
visitor.visit( this.collection );
}
}
class RockMusicVisitor implements MusicVisitor {
private final Set<Music> picks = ...
public visit(Set<Music> items) { ... }
public Set<Music> getRockMusic() { return this.picks; }
}
class AmbientMusicVisitor implements MusicVisitor {
private final Set<Music> picks = ...
public visit(Set<Music> items) { ... }
public Set<Music> getAmbientMusic() { return this.picks; }
}
You separate the data from the algorithm. You offload the algorithm to visitor implementations. You add functionality by creating more visitors, instead of constantly modifying (and bloating) the class that holds the data.
It provides another layer of abstraction. Reduces complexity of an object and makes it more modular. Sorta like using an interface(implementation being completely independent and no one cares how it is done just that it gets done.)
Now I have never used it but it would be useful for: Implementing a particular function that needs to be done in different subclasses, since each of the sub classes needs to implement it in different ways another class would implement all the functions. Kinda like a module but only for a collection of classes. Wikipedia has a pretty good explanation: http://en.wikipedia.org/wiki/Visitor_pattern
And their example helps explain what I am trying to say.
Hope that helps clear it up a bit.
EDIT**Sorry I linked to wikipedia for your answer but they really do have a decent example :) Not trying to be that guy that says go find it yourself.
Example of visitor pattern. Book, Fruit & Vegetable are basic elements of type "Visitable"
and there are two "Visitors" , BillingVisitor & OfferVisitor each of the visitor has its own purpose .Algo to calculate the bill and algo to calculate the offers on these elements is encapsulated in the respective visitor and the Visitables ( Elements) remain the same.
import java.util.ArrayList;
import java.util.List;
public class VisitorPattern {
public static void main(String[] args) {
List<Visitable> visitableElements = new ArrayList<Visitable>();
visitableElements.add(new Book("I123",10,2.0));
visitableElements.add(new Fruit(5,7.0));
visitableElements.add(new Vegetable(25,8.0));
BillingVisitor billingVisitor = new BillingVisitor();
for(Visitable visitableElement : visitableElements){
visitableElement.accept(billingVisitor);
}
OfferVisitor offerVisitor = new OfferVisitor();
for(Visitable visitableElement : visitableElements){
visitableElement.accept(offerVisitor);
}
System.out.println("Total bill " + billingVisitor.totalPrice);
System.out.println("Offer " + offerVisitor.offer);
}
interface Visitor {
void visit(Book book);
void visit(Vegetable vegetable);
void visit(Fruit fruit);
}
//Element
interface Visitable{
public void accept(Visitor visitor);
}
static class OfferVisitor implements Visitor{
StringBuilder offer = new StringBuilder();
#Override
public void visit(Book book) {
offer.append("Book " + book.isbn + " discount 10 %" + " \n");
}
#Override
public void visit(Vegetable vegetable) {
offer.append("Vegetable No discount \n");
}
#Override
public void visit(Fruit fruit) {
offer.append("Fruits No discount \n");
}
}
static class BillingVisitor implements Visitor{
double totalPrice = 0.0;
#Override
public void visit(Book book) {
totalPrice += (book.quantity * book.price);
}
#Override
public void visit(Vegetable vegetable) {
totalPrice += (vegetable.weight * vegetable.price);
}
#Override
public void visit(Fruit fruit) {
totalPrice += (fruit.quantity * fruit.price);
}
}
static class Book implements Visitable{
private String isbn;
private double quantity;
private double price;
public Book(String isbn, double quantity, double price) {
this.isbn = isbn;
this.quantity = quantity;
this.price = price;
}
#Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
static class Fruit implements Visitable{
private double quantity;
private double price;
public Fruit(double quantity, double price) {
this.quantity = quantity;
this.price = price;
}
#Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
static class Vegetable implements Visitable{
private double weight;
private double price;
public Vegetable(double weight, double price) {
this.weight = weight;
this.price = price;
}
#Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
}
I think the main purpose of visitor pattern is it has high extensibility. The intuition is you've bought a robot. The robot already has fully implemented elementary functionalities as go ahead, turn left, turn right, go back, pick something, speak a phase, …
One day, you want your robot can go to post office for you. With all of these elementary functionalities, it can do, but you need to bring you robot to the shop and "update" your robot. The shop seller do not need to modify the robot, but simply put a new update chip to your robot and it can do what you want.
An other day, you want your robot to go to supermarket. Same process, you has to bring your robot to the shop and update this "advanced" functionality. No need to modify the robot itself.
and so on …
So the idea of Visitor pattern is, given all implemented elementary functionalities, you can use visitor pattern to add an infinite number of sophisticated functionalities. In the example, the robot is your worker classes, and the "update chip" are visitors. Each time need a new "update" of functionality, you don't modify your worker class, but you add a visitor.
It is to separate the data manipulation from the actual data. As a bonus you can reuse the same visitor class for the whole hierarchy of your classes, which again saves you from carrying around the data manipulation algorithms that are irrelevant to your actual objects.