Suppose I have a class hierarchy in Java:
interface Item { ... };
class MusicBox implements Item { ... };
class TypeWriter implements Item { ... };
class SoccerBall implements Item { ... };
and I have another class in the same package:
class SpecialItemProcessor {
public void add(Item item)
{
/* X */
}
}
where I want to do something different for each item type, but I don't want to define that action in the different Item classes (MusicBox, TypeWriter, SoccerBall).
One way to handle this is:
class SpecialItemProcessor {
public void add(Item item)
{
if (item instanceof MusicBox)
{
MusicBox musicbox = (MusicBox)item;
... do something ...
}
else if (item instanceof MusicBox)
{
TypeWriter typewriter = (TypeWriter)item;
... do something ...
}
else if (item instanceof SoccerBall)
{
SoccerBall soccerball = (SoccerBall)item;
... do something ...
}
else
{
... do something by default ...
}
}
}
This works but it seems really clunky. Is there a better way to do this, when I know of special cases? (obviously if Item contains a method doSomethingSpecial then I can just call that item's method without caring what type it is, but if I don't want that differentiation to occur within the item itself how do I deal with it?)
In Java you can do multiple dispatch with a visitor(-like) pattern. The Item implementations don't need to contain the processing logic, they just need an accept() type of method.
public interface Item {
/** stuff **/
void processMe(ItemProcessor processor);
}
public interface ItemProcessor {
void process(MusicBox box);
void process(SoccerBall ball);
//etc
}
public class MusicBox implements Item {
#Override
public void processMe(ItemProcessor processor) {
processor.process(this);
}
}
public class ItemAddingProcessor implements ItemProcessor {
public void add(Item item) {
item.processMe(this);
}
#Override
public void process(MusicBox box) {
//code for handling MusicBoxes
//what would have been inside if (item instanceof MusicBox) {}
}
//etc
}
I think I'm going to use the idea of inversion of control and the visitor pattern:
interface Item {
public void accept(Visitor visitor);
...
public interface Visitor {
public void visit(Item item);
}
}
class MusicBox implements Item {
public interface Visitor extends Item.Visitor {
public void visitMusicBox(MusicBox item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof MusicBox.Visitor)
{
((MusicBox.Visitor)visitor).visitMusicBox(this);
}
}
}
class TypeWriter implements Item {
public interface Visitor extends Item.Visitor {
public void visitTypeWriter(TypeWriter item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof TypeWriter.Visitor)
{
((TypeWriter.Visitor)visitor).visitTypeWriter(this);
}
}
}
class SoccerBall implements Item {
public interface Visitor extends Item.Visitorr {
public void visitSoccerBall(SoccerBall item);
}
...
#Override public accept(Item.Visitor visitor)
{
if (visitor instanceof SoccerBall.Visitor)
{
((SoccerBall.Visitor)visitor).visitSoccerBall(this);
}
}
}
and then do the following, which at least reduces the instanceof to one check per add() call:
class SpecialItemProcessor
implements
MusicBox.Visitor,
TypeWriter.Visitor,
SoccerBall.Visitor,
Item.Visitor
{
public void add(Item item)
{
item.accept(this);
}
#Override public void visitMusicBox(MusicBox item)
{
...
}
#Override public void visitTypeWriter(TypeWriter item)
{
...
}
#Override public void visitSoccerBall(SoccerBall item)
{
...
}
#Override public void visit(Item item)
{
/* not sure what if anything I should do here */
}
}
Why not define some callback function to Item interface?
public Interface Item {
void onCallBack();
}
Then in each class that implements Item, such as MusicBox, it should implement the callback function.
public class MusicBox {
#override
public void onCallBack() {
// business logic
...
...
}
}
Then you could create a dispatcher, which you name is "SpecialItemProcessor".
public SpecialItemProcessor {
private final Item _item;
public SpecialItemProcessor(Item item) {
_item = item;
}
public dispatch() {
_item.onCallBack()
}
}
And then, in the Client class which contains the SpecialItemProcessor could just call the method, like:
public void XXXX() {
....
SpecialItemProcessor specialItemProcessor = new SpecialItemProcessor(new MusicBox());
specialItemProcessor.dispatch();
....
}
Actually, in C++, this is Dynamic Binding. And this is why pure abstract class exists...
You could create a bridge pattern for Item, in which the other side were the associated processes to do when add() is called. You could also add a factory method to the mix.
class SpecialItemProcessor {
public void add(Item item)
{
Process p = Item.createCorrespondingProcessor( p );
p.doWhenAddin();
}
}
Hope this helps.
Related
I have the following classes.
interface interface1() {
void function1()
}
interface interface2 extends interface1() {
void function2()
}
class implementation1 implements interface1 () {
#Override
void function1() {
// Implement
}
}
class implementation2 implements interface2 () {
#Override
void function1() {
// Implement
}
#Override
void function2() {
// Implement
}
}
class Main() {
List<interface1> interfaceList = new ArrayList();
for (interface : interfaceList) {
if (interface instanceOf(interface2)) {
interface.function2();
}
}
}
Could you please tell if there is a way to prevent using instanceOf? I read visitor pattern could be used but I am not getting the exact changes to be done.
Following are the classes after discussing with Alex R below (instanceOf is avoided since it is not recommended, visitor pattern is avoided since it still leads to empty visit functions). Please let me know if this can be done better using other design patterns.
interface interface1() {
void function1();
boolean isFunction2Applicable();
default void function2() {
}
}
class implementation1 implements interface1 () {
#Override
void function1() {
// Implement
}
#Override
boolean isFunction2Applicable() {
return false;
}
}
class implementation2 implements interface1 () {
#Override
void function1() {
// Implement
}
#Override
boolean isFunction2Applicable() {
return true;
}
#Override
void function2() {
// Implement
}
}
class Main() {
List<interface1> interfaceList = new ArrayList();
for (interface : interfaceList) {
if (interface.isFunction2Applicable()) {
interface.function2();
}
}
}
One way to do so is to define some method in the base interface and override it in the sub-interfaces or implementations. In the following example I'm using a default method but you don't have to do so; the method can be abstract and only be implemented in the implementations:
interface I1 {
void function1();
default void execute() {
function1();
}
}
interface I2 extends I1 {
void function2();
#Override
default void execute() {
function1();
function2();
}
}
public static void main(String[] args) {
List<I1> ifaces = new ArrayList<>();
for (I1 iface : ifaces) {
iface.execute();
}
}
At the moment I don't know how to avoid code smells in my piece of code.
I've tried several patterns (Strategy, Visitor) and they didn't provide a clean and maintainable solution. Here is an example of my code for strategy pattern:
public interface Strategy {
<T> T foo(FirstParam firstParam, SecondParam secondParam);
}
public class StrategyOne implements Strategy {
FirstReturnType foo(FirstParam firstParam, SecondParam secondParam);
}
public class StrategyTwo implements Strategy {
SecondReturnType foo(FirstParam firstParam, SecondParam secondParam);
}
#Setter
public class Context {
private Strategy strategy;
public void execute(FirstParam firstParam, SecondParam secondParam) {
if (strategy != null) {
strategy.fo(firstParam, secondParam);
}
}
}
And there is a example of objects.
public abstract class Action {
abstract void bar();
}
public class ActionOne extends Action {
void bar() {}
}
public class ActionTwo extends Action {
void bar() {}
}
And I want to make this piece of code cleaner
public class ActionExecutor {
private Context context;
private FirstParam firstParam;
private SecondParam secondParam;
public ActionExecutor(FirstParam firstParam, SecondParam secondParam) {
this.context = new Context();
this.firstParam = firstParam;
this.secondParam = secondParam;
}
public void doSmth(Item item) {
Action action = item.getAction();
if(action instanceof ActionOne) {
context.setStrategy(new StrategyOne());
}
if(action instanceof ActionTwo) {
context.setStrategy(new StrategyTwo());
}
context.execute(firstParam, secondParam);
}
}
The idea is to perform a specific action for a specific object type. But I don't know how to avoid the usage of instanceof in this situation.
Two ways top of my head.
public abstract class Action {
public Strategy strategy;
abstract void bar();
}
public class ActionOne extends Action {
void bar() {}
// set strategy here, possibly
}
public class ActionTwo extends Action {
void bar() {}
}
public void doSmth(Item item) {
Action action = item.getAction();
action.strategy.execute(firstParam, secondParam);
}
Second way, have an enum in all your actions and force it by declaring it as a parameter in your abstract class constructor. Then just use switch in instead of instanceof
Could be something like this:
public void doSmth(Item item) {
Action action = item.getAction();
Map<String,Strategy> strategies = new HashMap<>();
strategies.put(ActionOne.getClass().getSimpleName(),new StrategyOne());
strategies.put(ActionTwo.getClass().getSimpleName(),new StrategyTwo());
..
strategies.put(ActionHundred.getClass().getSimpleName(),new StrategyHundred());
if(strategies.containsKey(action.getClass().getSimpleName())) {
context.setStrategy(strategies.get(action.getClass().getSimpleName()));
}
context.execute(firstParam, secondParam); }
This seems like a textbook use case for the Factory Method pattern. You can use the same code you have now (or the Map example in another answer), but put it in a factory - then it's purpose-specific and decoupled from the code that uses it.
Something like this.
public class StrategyFactory {
public static Stategy getStrategy(Action action) {
if(action instanceof ActionOne) {
return new StrategyOne();
} else if(action instanceof ActionTwo) {
return new StrategyTwo();
}
}
}
And then, something like this.
Action action = item.getAction();
action.setStrategy(StrategyFactory.getStrategy(action));
There's another example here: https://dzone.com/articles/design-patterns-the-strategy-and-factory-patterns
public abstract class CommonClass {
abstract void send(<what should i put here???>) {}
}
public class ClassA extends CommonClass {
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass {
void send(List<Post> postList) {
// do stuff
}
}
I am new to OODP, I am trying to have a method that is able to take in any kind of List data so that I can abstract things out. How can i do this?
You could make it generic on some type T. Like,
public abstract class CommonClass<T> {
abstract void send(List<T> al);
}
And then, to implement it - use the generic. Like,
public class ClassA extends CommonClass<Comments> {
#Override
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
Also, as discussed in the comments, your class names could be improved to be more intuitive; something like,
public abstract class AbstractSender<T> {
abstract void send(List<T> al);
}
and then
public class CommentSender extends AbstractSender<Comment> {
#Override
void send(List<Comment> commentsList) {
// do stuff
}
}
public class PostSender extends AbstractSender<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
That has the advantage(s) of being more readable and easier to reason about (I can tell what a PostSender does by reading the name, ClassB not so much).
Finally, this looks like a case where an interface would work since your abstract class is purely virtual (and should be preferred since you can implement multiple interface, but can only extend from a single parent class);
public interface ISender<T> {
void send(List<T> al);
}
public class CommentSender implements ISender<Comment> {
#Override
void send(List<Comment> commentsList) {
// do stuff
}
}
public class PostSender implements ISender<Post> {
#Override
void send(List<Post> postList) {
// do stuff
}
}
In order to achieve this, you can take multiple approaches, I would suggest looking into Generics: https://docs.oracle.com/javase/tutorial/java/generics/index.html
With that said, there is one approach that is the most elegant and simple: you can supply a List<T> where T is a generic type.
public abstract class CommonClass<T> {
abstract void send(List<T>) {}
}
public class ClassA extends CommonClass<Comment> {
void send(List<Comments> commentsList) {
// do stuff
}
}
public class ClassB extends CommonClass<Post> {
void send(List<Post> postList) {
// do stuff
}
}
You can do that with the help of generics. https://www.tutorialspoint.com/java/java_generics.htm
Example
The abstract class
public abstract class CommonClass {
public abstract <T> void send(List<T> data);
}
Its child
public class Child extends CommonClass {
public <T> void send(List<T> data) {
// code here
}
}
Retrieving the list's contents
Retrieving the generified list's contents is similar to retrieving any list's contents. In the scope of the method, "T" is a type of object contained in the list.
for (T t : data) {
// to check if t is a string
if (t instanceof String) {
// code
}
}
You can also use lambdas to retrieve every element in the list.
I have some handlers who implements interface. Each handler should serve some cases according to one or more types. I get the list of that handlers via autowired.
So when I want to use these handler in the iterate over them and check whether some of them handle the case, if so I run it on the case.
As describe here -
#Service
public class CarCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.Car);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
#Service
public class HouseCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.House);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
#Service
public class AnimalCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.Animal);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
interface ICreator{
boolean shouldServe(IEntity entity);
public boolean crate(IEntity entity);
}
public void EntitiesCreatorManger{
List<ICreator> creators;
#Autowired
public EntitiesCreatorManger(List<ICreator> creators){ this.creators = creators;}
public void createEntities(List<IEntity> entitites){
entities.stream.forEach(entity-> {
for(ICreator creator : creators){
if(creator.shouldServe(entity){
creator.create(entity);
break;
}
}
}
}
I want to do it with more elegant way and not for each list of interfaces in my system to use like this. Is there such way?
put all your ICreators in a lookup map:
Map<IEntity, ICreator> map = ...
ICreator creator = map.get(entity);
if(creator != null) {
...}
You seem to have an enumeration of types. Move the create logic onto the enum instances, and delegate to the create() call to the type.
public enum Type implements ICreator {
Car {
#Override
public void create(IEntity entity) {
// car creation
}
},
House {
#Override
public void create(IEntity entity) {
// house creation
}
},
Animal{
#Override
public void create(IEntity entity) {
// animal creation
}
};
}
public void EntitiesCreatorManager{
public void createEntities(List<IEntity> entities){
entities.forEach(entity -> entity.getType().create(entity));
}
}
here's a programming style question about the best strategy to map input keys to actions in a class that implement the state pattern.
I'm dealing with two classes:
The first implements the state pattern, which controls a multi-state physical device:
class DeviceController {
State _a, _b, _current;
// Actions that may prompt a transition from one state to another
public void actionA() { ... }
public void actionB() { ... }
public void actionC() { ... }
public State getStateA() { ... }
public State getStateB() { ... }
public void setCurrentState() { ... }
};
The second is a KeyListener that retrieves all keyboard input and calls the appropriate action from the device controller when a pressed input key matches a (for the time being) hard-coded bindings table:
class KeyDemo implements KeyListener {
DeviceController _controller;
...
#Override
public void keyPressed(KeyEvent arg0) {
char key = Character.toUpperCase(arg0.getKeyChar());
switch (key) {
case 'A':
_controller.actionA();
break;
case 'B' :
...
}
...
}
Is there a best-practice coding style to bind the keys to the actions in the controller ? Do I have to go through a switch statement, as in the sample code ? It seems to me that this solution is somewhat dirty code: isn't the state pattern supposed to eliminate unmaintanable if and switch control structures ?
Thank you for your suggenstions.
Using polymorphism you can achive your goal. I've used enum but maybe it would be more appropriated to use interfaces or an abstract class and then implement each of the key processors. What do you think?
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
enum KeyProcessor {
A {
void executeAction() {
_controller.actionA();
}
},
B {
void executeAction() {
_controller.actionB();
}
};
private static final DeviceController _controller = new DeviceController();
void executeAction() {
System.out.println("no action defined");
}
}
class DeviceController {
State _a;
State _b;
State _current;
// Actions that may prompt a transition from one state to another
public void actionA() {
System.out.println("action A performed.");
}
public void actionB() {
System.out.println("action B performed.");
}
public void actionC() {
}
public State getStateA() {
return null;
}
public State getStateB() {
return null;
}
public void setCurrentState() {
}
} // end class DeviceController
public class KeyDemo implements KeyListener {
DeviceController _controller;
// ...
#Override
public void keyPressed(KeyEvent arg0) {
keyPressed(Character.toUpperCase(arg0.getKeyChar()));
// ...
}
public void keyPressed(char c) {
KeyProcessor processor = KeyProcessor.valueOf(c + "");
if (processor != null) {
processor.executeAction();
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
public static final void main(String[] args) {
KeyDemo main = new KeyDemo();
main.keyPressed('A');
main.keyPressed('B');
}
} // end class KeyDemo
class State {
}