Visitor pattern's purpose with examples [duplicate] - java

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.

Related

Object oriented Design: Scalable and maintainable car store system

I had an interview yesterday and had asked an OOD question:
Race-Car Store System:
The system stores information about cars available for players.
Two types of gear changing strategies: manual/automatic.
Two types of fuel: gasoline/diesel.
Design a system that can produce cars requested by players (If the
player wants a car with manual gear changing and burn diesel, your
system should provide one instance of the car meets the requirements).
The system should have good scalability and maintainability.
My thoughts and solution:
My thought is the requirement contains two attributes: gear and fuel. I plan to make an abstract class contains the attributes and corresponding behaviors. Considering scalability would have an interface Movable which contains behaviors what a car can do.
If any new attribute is added in the future, either create a new abstract class contains the new attribute or add the attribute into the existing abstract class, if there's new behaviors are required, I would either create new interface or add the behavior into existing interface.
Here's what I have done:
An interface contains general behaviors, currently has showSpecs() only.
public interface Movable {
public String showSpecs();
}
An abstract class contains attributes fuel and gear
public abstract class Car implements Movable {
String gear;
String fuel;
abstract void setFuel(String fuel);
abstract String getFuel();
abstract void setGear(String gear);
abstract String getGear();
}
Now the race car class implementaion:
public class RaceCar extends Car {
public RaceCar(String fuel, String gear) {
this.fuel = fuel;
this.gear = gear;
}
public void setFuel(String fuel) {
this.fuel = fuel;
}
public String getFuel() {
return this.fuel;
}
public void setGear(String gear) {
this.gear = gear;
}
public String getGear() {
return this.gear;
}
public String showSpecs() {
StringBuilder sb = new StringBuilder();
sb.append("Gear:").append(this.gear);
sb.append("Fuel:").append(this.fuel);
return sb.toString();
}
}
Below is the main class I have:
public class Main {
public static void main(String[] args) {
System.out.println("get started...");
Car car = new RaceCar("diseal", "automatic");
System.out.println(car.showSpecs());
}
}
The interviewer replied that the solution I provided is not scalable and hard to maintain but didn't provide details so I am still confused about what mistakes I made and how to improve it.
Can anyone help share your thoughts and point out what am I supposed to improve?
Thanks!
I would have answered this question with 2 classes, Car and CarBuilder:
public final class Car {
private final Fuel fuel;
private final Gears gears;
public Car(Fuel fuel, Gears gears) {
this.fuel = fuel;
this.gears = gears;
}
public Fuel getFuel() {
return fuel;
}
public Gears getGears() {
return gears;
}
enum Fuel {
GASOLINE,
DEISEL
}
enum Gears {
AUTOMATIC,
MANUAL
}
}
public class CarBuilder {
//sensible defaults:
private Car.Fuel fuel = Car.Fuel.GASOLINE;
private Car.Gears gears = Car.Gears.MANUAL;
public CarBuilder() {
}
public CarBuilder withFuelType(Car.Fuel fuel) {
this.fuel = fuel;
return this;
}
public CarBuilder withGearBox(Car.Gears gears) {
this.gears = gears;
return this;
}
public Car build() {
return new Car(this.fuel, this.gears);
}
}
Scalability and maintainability is achieved by the fact that these are the only 2 classes that need to be changed in the future, should requirements change. Car is immutable and also contains the enums required to represent its internal state, so these attributes can't leak out of the context/object in which they make sense so make it easier to maintain in the future.
The builder class, while basic in its current form, can be extended to accommodate more complex construction requirements without leaking implementation details into the Car class.
The default values are optional, but might make sense.
A car can be constructed as such:
//Default car:
Car car = new CarBuilder().build();
//Customised car:
Car car = new CarBuilder().withFuelType(Car.Fuel.DEISEL).withGearBox(Car.Gears.AUTOMATIC).build();
I thought that maybe he was expecting something like pluggable classes when he mentioned scalable and maintainable. So I think maybe this strategy pattern was expected. If transmission or injection is expected to do some real logic, I can assume them as behaviors instead of just state. Thus results with this implementation.
public interface TransmissionPolicy {
public void transmit();
}
public class AutomaticTransmission implements TransmissionPolicy {
public void transmit() {
//do some real logic here
print("automatic...");
}
}
public class ManualTransmission implements TransmissionPolicy {
public void transmit() {
print("we love it..."); //just an example of really simple logic
}
}
public interface InjectionPolicy {
public void inject();
}
public class DieselInjection implements InjectionPolicy {
public void inject() {
print("diesel");
}
}
public class GasolineInjection implements InjectionPolicy {
public void inject() {
print("gasoline...");
}
}
public class Car {
public void make(TransmissionPolicy transmission, InjectionPolicy injection) {
//set other parts
transmission.transmit();
//set other parts
injection.inject();
//other parts
}
}
//--------------somewhere in some clients client --------------------
Car car = new Car();
//actually, to be really configurable use a factory method here.
car.make(new ManualTransmission(), new GasolineInjection());
If that was expected then with just lambdas or command pattern it would be made also.

How to create a new object based on interface implementation

Firstly, I believe my question is badly worded but don't really understand how to phrase it.
I have a starting interface that is being implemented by a number of classes. What I want to do is to see if there is a way to create a new object such that I am being passed the generic interface, then based on the method .getClass().getSimpleName(), create a new object based on that string.
Is the only way to create a switch case statement? As the number of implementing classes are too many (about 100 or so).
Reference code:
public interface MyInterface {
public void someMethod();
}
then I would have my implementing classes:
public class MyClass1 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass2 implements MyInterface {
public void someMethod() { //statements }
}
public class MyClass3 implements MyInterface {
public void someMethod() { //statements }
}
What I want to have in the end is another class which is passed an argument of type MyInterface, get the simple name from that and create a new instance of MyClassX based on that simple name.
public class AnotherClass {
public void someMethod(MyInterface interface) {
if (interface == null) {
System.err.println("Invalid reference!");
System.exit(-1);
} else {
String interfaceName = interface.getClass().getSimpleName();
/**
* This is where my problem is!
*/
MyInterface newInterface = new <interfaceName> // where interfaceName would be MyClass1 or 2 or 3...
}
}
}
Any help is highly appreciated!
You can use reflection for this:
public void someMethod(MyInterface myInterface) {
Class<MyInterface> cl = myInterface.getClass();
MyInteface realImplementationObject = cl.newInstance(); // handle exceptions in try/catch block
}
This is a common problem with many solutions. When I face it, I never use reflection because it is difficult to maintain if it is part of a big project.
Typically this problem comes when you have to build an object based on a user selection. You can try a Decorator pattern for that. So, instead of building a different object for each option. You can build a single object adding functionality depending on a selection. For instance:
// you have
Pizza defaultPizza = new BoringPizza();
// user add some ingredients
Pizza commonPizza = new WithCheese(defaultPizza);
// more interesting pizza
Pizza myFavorite = new WithMushroom(commonPizza);
// and so on ...
// then, when the user checks the ingredients, he will see what he ordered:
pizza.ingredients();
// this should show cheese, mushroom, etc.
under the hood:
class WithMushroom implements Pizza {
private final Pizza decorated;
public WithMushroom(Pizza decorated) {
this.decorated = decorated;
}
#Override
public Lizt<String> ingredients() {
List<String> pizzaIngredients = this.decorated.ingredients();
// add the new ingredient
pizzaIngredients.add("Mushroom");
// return the ingredients with the new one
return pizzaIngredients;
}
}
The point is that you are not creating an object for each option. Instead, you create a single object with the required functionality. And each decorator encapsulates a single functionality.

Java implementing business logic based on EnumType given as field of Object

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();

Extending a java ArrayList

I'd like to extend ArrayList to add a few methods for a specific class whose instances would be held by the extended ArrayList. A simplified illustrative code sample is below.
This seems sensible to me, but I'm very new to Java and I see other questions which discourage extending ArrayList, for example Extending ArrayList and Creating new methods. I don't know enough Java to understand the objections.
In my prior attempt, I ending up creating a number of methods in ThingContainer that were essentially pass-throughs to ArrayList, so extending seemed easier.
Is there a better way to do what I'm trying to do? If so, how should it be implemented?
import java.util.*;
class Thing {
public String name;
public int amt;
public Thing(String name, int amt) {
this.name = name;
this.amt = amt;
}
public String toString() {
return String.format("%s: %d", name, amt);
}
public int getAmt() {
return amt;
}
}
class ThingContainer extends ArrayList<Thing> {
public void report() {
for(int i=0; i < size(); i++) {
System.out.println(get(i));
}
}
public int total() {
int tot = 0;
for(int i=0; i < size(); i++) {
tot += ((Thing)get(i)).getAmt();
}
return tot;
}
}
public class Tester {
public static void main(String[] args) {
ThingContainer blue = new ThingContainer();
Thing a = new Thing("A", 2);
Thing b = new Thing("B", 4);
blue.add(a);
blue.add(b);
blue.report();
System.out.println(blue.total());
for (Thing tc: blue) {
System.out.println(tc);
}
}
}
Nothing in that answer discourages extending ArrayList; there was a syntax issue. Class extension exists so we may re-use code.
The normal objections to extending a class is the "favor composition over inheritance" discussion. Extension isn't always the preferred mechanism, but it depends on what you're actually doing.
Edit for composition example as requested.
public class ThingContainer implements List<Thing> { // Or Collection based on your needs.
List<Thing> things;
public boolean add(Thing thing) { things.add(thing); }
public void clear() { things.clear(); }
public Iterator<Thing> iterator() { things.iterator(); }
// Etc., and create the list in the constructor
}
You wouldn't necessarily need to expose a full list interface, just collection, or none at all. Exposing none of the functionality greatly reduces the general usefulness, though.
In Groovy you can just use the #Delegate annotation to build the methods automagically. Java can use Project Lombok's #Delegate annotation to do the same thing. I'm not sure how Lombok would expose the interface, or if it does.
I'm with glowcoder, I don't see anything fundamentally wrong with extension in this case--it's really a matter of which solution fits the problem better.
Edit for details regarding how inheritance can violate encapsulation
See Bloch's Effective Java, Item 16 for more details.
If a subclass relies on superclass behavior, and the superclass's behavior changes, the subclass may break. If we don't control the superclass, this can be bad.
Here's a concrete example, lifted from the book (sorry Josh!), in pseudo-code, and heavily paraphrased (all errors are mine).
class CountingHashSet extends HashSet {
private int count = 0;
boolean add(Object o) {
count++;
return super.add(o);
}
boolean addAll(Collection c) {
count += c.size();
return super.addAll(c);
}
int getCount() { return count; }
}
Then we use it:
s = new CountingHashSet();
s.addAll(Arrays.asList("bar", "baz", "plugh");
And it returns... three? Nope. Six. Why?
HashSet.addAll() is implemented on HashSet.add(), but that's an internal implementation detail. Our subclass addAll() adds three, calls super.addAll(), which invokes add(), which also increments count.
We could remove the subclass's addAll(), but now we're relying on superclass implementation details, which could change. We could modify our addAll() to iterate and call add() on each element, but now we're reimplementing superclass behavior, which defeats the purpose, and might not always be possible, if superclass behavior depends on access to private members.
Or a superclass might implement a new method that our subclass doesn't, meaning a user of our class could unintentionally bypass intended behavior by directly calling the superclass method, so we have to track the superclass API to determine when, and if, the subclass should change.
I don't think extending arrayList is necessary.
public class ThingContainer {
private ArrayList<Thing> myThings;
public ThingContainer(){
myThings = new ArrayList<Thing>();
}
public void doSomething(){
//code
}
public Iterator<Thing> getIter(){
return myThings.iterator();
}
}
You should just wrap ArrayList in your ThingContainer class. ThingContainer can then have any processing methods you need. No need to extend ArrayList; just keep a private member.
Hope this helps.
You may also want to consider creating an interface that represents your Thing Class. This gives you more flexibility for extensibility.
public Interface ThingInterface {
public void doThing();
}
...
public OneThing implements ThingInterface {
public void doThing(){
//code
}
}
public TwoThing implements ThingInterface {
private String name;
public void doThing(){
//code
}
}
Here is my suggestion:
interface ThingStorage extends List<Thing> {
public int total();
}
class ThingContainer implements ThingStorage {
private List<Thing> things = new ArrayList<Thing>();
public boolean add(Thing e) {
return things.add(e);
}
... remove/size/... etc
public int total() {
int tot = 0;
for(int i=0; i < size(); i++) {
tot += ((Thing)get(i)).getAmt();
}
return tot;
}
}
And report() is not needed actually. toString() can do the rest.

How to deal with Java Polymorphism in Service Oriented Architecture

What is the path of least evil when dealing with polymorphism and inheritance of entity types in a service-oriented architecture?
A principle of SOA (as I understand it) is to have entity classes as mere data constructs, lacking in any business logic. All business logic is contained in narrow-scoped, loosely-coupled services. This means service implementations are as small as possible furthering the loose coupling, and means the entities avoid having to know about every behaviour the system may perform on them.
Due to Java's quite baffling decision to use the declared type when deciding which overloaded method to use, any polymorphic behaviour in the service implementations is instead replaced with a series of conditionals checking object.getClass() or using instanceof. This seems rather backward in an OOPL.
Is the use of conditionals the accepted norm in SOA? Should inheritance in entities be abandoned?
UPDATE
I definitely mean overloading and not overriding.
I define SOA to mean that behaviour of the system is grouped by use case into interfaces, and then the logic for these is implemented in one class per interface, generally. As such an entity class (say Product) becomes nothing more than a POJO with getters and setters. It absolutely should not contain any business logic related to a service, because then you introduce one focal point of coupling whereby the entity class needs to know about all business processes that may ever operate on it, completely negating the purpose of a loosely-coupled SOA.
So, being that one should not embed business process-specific behaviour in an entity class, one cannot use polymorphism with these entity classes - there is no behaviour to override.
UPDATE 2
The above behaviour is more simply explained as an overloaded path is chosen at compile-time, and an overridden path at run-time.
It'd be bad practice to have a subclass of your service implementation for each subtype of the domain model class it's acting on, so how do people get around the overloading-at-compile-time issue?
You can avoid this problem by designing the business logic in different classes based on the entity type, based on single responsibility principle it would be the best way to go when you place business logic in a service layer and use a factory to create logic implementation, for example
enum ProductType
{
Physical,
Service
}
interface IProduct
{
double getRate();
ProductType getProductType();
}
class PhysicalProduct implements IProduct
{
private double rate;
public double getRate()
{
return rate;
}
public double getProductType()
{
return ProductType.Physical;
}
}
class ServiceProduct implements IProduct
{
private double rate;
private double overTimeRate;
private double maxHoursPerDayInNormalRate;
public double getRate()
{
return rate;
}
public double getOverTimeRate()
{
return overTimeRate;
}
public double getMaxHoursPerDayInNormalRate;()
{
return maxHoursPerDayInNormalRate;
}
public double getProductType()
{
return ProductType.Service;
}
}
interface IProductCalculator
{
double calculate(double units);
}
class PhysicalProductCalculator implements IProductCalculator
{
private PhysicalProduct product;
public PhysicalProductCalculator(IProduct product)
{
this.product = (PhysicalProduct) product;
}
double calculate(double units)
{
//calculation logic goes here
}
}
class ServiceProductCalculator implements IProductCalculator
{
private ServiceProduct product;
public ServiceProductCalculator(IProduct product)
{
this.product = (ServiceProduct) product;
}
double calculate(double units)
{
//calculation logic goes here
}
}
class ProductCalculatorFactory
{
public static IProductCalculator createCalculator(IProduct product)
{
switch (product.getProductType)
{
case Physical:
return new PhysicalProductCalculator ();
case Service:
return new ServiceProductCalculator ();
}
}
}
//this can be used to execute the business logic
ProductCalculatorFactory.createCalculator(product).calculate(value);
It took me a while from reading this to work out what you were really asking for.
My interpretation is that you have a set of POJO classes where when passed to a service you want the service to be able to perform different operations depending on the the particular POJO class passed to it.
Usually I'd try and avoid a wide or deep type hierarchy and deal with instanceof etc. where the one or two cases are needed.
When for whatever reason there has to be a wide type hierarchy I'd probably use a handler pattern kind of like below.
class Animal {
}
class Cat extends Animal {
}
interface AnimalHandler {
void handleAnimal(Animal animal);
}
class CatHandler implements AnimalHandler {
#Override
public void handleAnimal(Animal animal) {
Cat cat = (Cat)animal;
// do something with a cat
}
}
class AnimalServiceImpl implements AnimalHandler {
Map<Class,AnimalHandler> animalHandlers = new HashMap<Class, AnimalHandler>();
AnimalServiceImpl() {
animalHandlers.put(Cat.class, new CatHandler());
}
public void handleAnimal(Animal animal) {
animalHandlers.get(animal.getClass()).handleAnimal(animal);
}
}
Due to Java's quite baffling decision to use the declared type when
deciding which overloaded method to use
Whoever gave you that idea? Java would be a worthless language if it were like that!
Read this: Java Tutorial > Inheritance
Here's a simple test program:
public class Tester{
static class Foo {
void foo() {
System.out.println("foo");
}
}
static class Bar extends Foo {
#Override
void foo() {
System.out.println("bar");
}
}
public static void main(final String[] args) {
final Foo foo = new Bar();
foo.foo();
}
}
The Output is of course "bar", not "foo"!!
I think there is a confusion of concerns here. SOA is an architectural way to solve interaction between components. Each component within a SOA solution will handle a context within a larger domain. Each context is a domain of it self. In other words, SOA is something that allows for lose coupling in between domain contexts, or applications.
Object Orientation in Java, when working in this kind of an environment, will apply to each domain. So hierarchies and rich domain objects modelled using something like domain driven design will live on a level below the services in a SOA solution. There is a tier between the service exposed to other contexts and the detailed domain model which will create rich objects for the domain to work with.
To solve each context/applications architecture with SOA will not provide a very good application. Just as solving the interaction between them using OO.
So to try to answer the bounty question more specifically:
It's not a matter of engineering around the issue. It's a matter of applying the correct pattern to each level of design.
For a large enterprise ecosystem SOA is the way I would solve interaction in between systems, for example HR system and payroll. But when working with HR (or probably each context within HR) and payroll I would use the patterns from DDD.
I hope that clears the waters a bit.
Having thought about this a bit more I've thought on an alternative approach that makes for a simpler design.
abstract class Animal {
}
class Cat extends Animal {
public String meow() {
return "Meow";
}
}
class Dog extends Animal {
public String bark() {
return "Bark";
}
}
class AnimalService {
public String getSound(Animal animal) {
try {
Method method = this.getClass().getMethod("getSound", animal.getClass());
return (String) method.invoke(this, animal);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getSound(Cat cat) {
return cat.meow();
}
public String getSound(Dog dog) {
return dog.bark();
}
}
public static void main(String[] args) {
AnimalService animalService = new AnimalService();
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Cat());
animals.add(new Dog());
for (Animal animal : animals) {
String sound = animalService.getSound(animal);
System.out.println(sound);
}
}

Categories

Resources