Consider a method
public void doSomething(String actionID){
switch (actionID){
case "dance":
System.out.print("I'm dancing");
break;
case "sleep":
System.out.print("I'm sleeping");
break;
default:
System.out.print("I've no idea what I'm doing");
}
The implementation of the method depends on the value of the parameter. Is there a more elegant way to do this, or a different design pattern to replicate the behaviour?
If the caller decides what logic is executed by passing different strings, then why not just have them call different methods:
public void doSomething(String actionID) {...}
...
doSomething("dance");
doSomething("sleep");
VS.:
public void dance() {...}
public void sleep() {...}
...
dance();
sleep();
It seems like you're unnecessarily funnelling all the calls into doSomething
But the strings might not always be literals. What if you're taking them from the console?
You could provide static mappings from the strings to the corresponding functions:
class MyClass {
private static final Map<String, Consumer<MyClass>> map = new HashMap<>();
static {
map.put("sleep", MyClass::sleep);
map.put("dance", MyClass::dance);
}
public void doSomething(String actionID) {
map.getOrDefault(actionID, MyClass::doNothing).accept(this);
}
public void dance() {
System.out.print("I'm dancing");
}
public void sleep() {
System.out.print("I'm sleeping");
}
private void doNothing() {
System.out.println("I've no idea what I'm doing");
}
}
This makes scenarios where you have a lot of switch cases a lot cleaner.
Introduce an interface, e.g.
public interface HumanState {
public void tellMeWhatYouAreDoing();
}
encapsulate the logic in different implementations
public class DancingState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I'm dancing");
}
}
public class SleepingState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I'm sleeping");
}
}
public class UnknownState implements HumanState {
#Override
public void tellMeWhatYouAreDoing() {
System.out.println("I've no idea what I'm doing");
}
}
and use a map. E.g.
public class HumanStateExample {
public static void main(String[] args) {
HumanStateExample humanStateExample = new HumanStateExample();
humanStateExample.doSomething("dance");
humanStateExample.doSomething("sleep");
humanStateExample.doSomething("unknown");
}
private final HashMap<String, HumanState> humanStateMap;
public HumanStateExample(){
humanStateMap = new HashMap<String, HumanState>();
humanStateMap.put("dance", new DancingState());
humanStateMap.put("sleep", new SleepingState());
}
public void doSomething(String action) {
HumanState humanState = humanStateMap.get(action);
if(humanState == null){
humanState = new UnknownState();
}
humanState.tellMeWhatYouAreDoing();
}
}
I'm not sure how the pattern is called, but it is very useful if you need to delegate the method call based on more than one parameter:
Create a lot of handlers where each one knows when it is responsible for handling a call. Then just loop through them and invoke the first one matching the parameter.
edit: I renamed the class from FancyParameterActionFactory to FancyParameterActionUtility: it is not a factory, the name was misleading
//Your method, but this time with a complex object, not with a simple string.
public void doSomething(FancyParameterObject fpo){
FancyParameterActionUtility.invokeOn(fpo);
}
//The utility which can handle the complex object and decides what to do.
public class FancyParameterActionUtility{
public Interface FPAHandler{
void invoke(FancyParameterObject fpo);
boolean handles(FancyParameterObject fpo);
}
//Omitted: Different implementations of FPAHandler
public static List<FPAHandler> handlers = new LinkedList<>();
static{
handlers.add(new DanceHandler());
handlers.add(new SleepHandler());
//Omitted: Different implementations of FPAHandler
}
public static void invokeOn(FancyParameterObject fpo){
for(FPAHandler handler:handlers){
if (handler.handles(fpo)){
handler.invoke(fpo);
return;
}
}
//Default-Behavior
}
}
Here is a simple implementation of the command pattern based your sample problem. I define a general AbstractCommand abstract class which contains two methods. The first method, createCommand(), instantiates a command class based on an input string name. This is how you can delegate your string input to create the right type of command. The second method is doAction(), and this is left undefined, to be implemented later on by specific concrete command classes.
public abstract class AbstractCommand {
public static AbstractCommand createCommand(String name) {
try {
String clsName = name + "Command";
Class<?> cls = Class.forName(clsName);
AbstractCommand command = (AbstractCommand) cls.newInstance();
return command;
}
catch (Exception e) {
System.out.println("Something went wrong.");
}
}
public abstract void doAction();
}
public class DanceCommand extends AbstractCommand {
public void doAction() {
System.out.println("I'm dancing");
}
}
public class TestCommandPattern {
public void doSomething(String actionID) {
AbstractCommand cmd = AbstractCommand.createCommand(actionID);
cmd.doAction();
}
public static void main(String[] args) {
TestCommandPattern test = new TestCommandPattern();
test.doSomething("Dance"); // should print "I'm dancing"
}
}
Now that this framework has been setup, you could easily add other commands for the various types of actions in your original problem. For example, you could create a SleepCommand class which would output I'm sleeping, or do whatever action you wish.
Related
So i'm trying to develop a fluent interface for some DSL in Java and am running into a problem. The interface consists of builder pattern classes that each construct part of the DSL. The problem is that a specific builder sometimes needs to transfer control to a different builder which at some point returns to the 'parent' builder. For example, there is a 'SequenceBuilder' that creates a list of statements but it need sometimes transfer control to an 'IfBuilder' that is used to create an 'if' statement. When the IfBuilder is finished, it needs to return to the SequenceBuilder. Now there are some builders that are not always called by the same type of other builder and therefore need to be able to return builders of a different datatype. The example program below demonstrates this:
package com.example.fluent;
public class Test {
public class Type1 {
public Type1 test1() {
System.out.println("test1");
return this;
}
public Type3 gotype3() {
System.out.println("gotype3");
return new Type3<Type1>(this);
}
public void endtype1() {
System.out.println("endtype1");
}
}
public class Type2 {
public Type2 test2() {
System.out.println("test2");
return this;
}
public Type3 gotype3() {
System.out.println("gotype3");
return new Type3<Type2>(this);
}
public void endtype2() {
System.out.println("endtype2");
}
}
public class Type3<T> {
private T parent;
public Type3(T parent) {
this.parent = parent;
}
public Type3 test3() {
System.out.println("test3");
return this;
}
public T endtype3() {
System.out.println("endtype3");
return parent;
}
}
public static void main(String[] args) {
new Test().run();
}
private void run() {
new Type1()
.test1()
.gotype3()
.test3()
.endtype3()
.test1()
.endtype1();
}
}
You can see in the .run() method that i start by creating a new instance of the Type1 class, which follows the builder pattern. At some point i'm calling the .goType3() method which transfers control to the Type3 builder. Because it has to return control at some point to Type1 again, a reference to that builder is passed via constructor to Type3. When it's time to return to Type1, the method .endtype3() is called. And here lies the problem. I'm using generics to (try) to return the datatype of Type1 but instead it's converted to an Object type. That datatype obviously does not have the methods that Type1 has and therefore the pattern is broken.
Question: is there some other way to return the proper datatype to the parent builder?
You're not using generics as much as you want to. You're using return type Type3. You need to use Type3<Type1>, Type3<Type2> and Type3<T> instead.
Thanks to Rob Spoor i got my code finally working, though i didn't understand it at first. The solution lies in changing the code in the following ways:
package com.example.fluent;
public class Test {
public class Type1 {
public Type1 test1() {
System.out.println("test1");
return this;
}
public Type3<Type1> gotype3() {
System.out.println("gotype3");
return new Type3<Type1>(this);
}
public void endtype1() {
System.out.println("endtype1");
}
}
public class Type2 {
public Type2 test2() {
System.out.println("test2");
return this;
}
public Type3<Type2> gotype3() {
System.out.println("gotype3");
return new Type3<Type2>(this);
}
public void endtype2() {
System.out.println("endtype2");
}
}
public class Type3<T> {
private T parent;
public Type3(T parent) {
this.parent = parent;
}
public Type3<T> test3() {
System.out.println("test3");
return this;
}
public T endtype3() {
System.out.println("endtype3");
return parent;
}
}
public static void main(String[] args) {
new Test().run();
}
private void run() {
// new Type1().test1().test1().endtype1();
new Type1().test1().gotype3().test3().endtype3().test1().endtype1();
// new Type2().test2().gotype3().test3().endtype3().test2().endtype2();
}
}
See the changes in the return types of the .gotype3() methods in the Type1 and Type2 classes, as well as the return type of the .test3() method. Now everything is working fine.
I have a code block like below:
public Interface ISupClass{
void call();
void call1();
...
}
public class NormalClass implements ISupClass{
void call(){
....operations...
}
void call1(){
....operations...
}
...
}
public class DailyClass implements ISupClass{
void call(){
....operations...
}
void call1(){
....operations...
}
...
}
Then I call them from main service like that;
Instances:
private INormalClass dailyClass = new DailyClass();
private INormalClass normalClass = new NormalClass();
Method:
public void call(int type, boolean isDaily){
if(type == 0) {
if(isDaily){
dailyClass.call();
}
else{
normalClass.call();
}
}
if(type == 1) {
if(isDaily){
dailyClass.call1();
}
else{
normalClass.call1();
}
}
...
}
Is there a way to escape from isDaily check in above code block? Or how can I implement it effectively? I have just tried to implement with Java Generics but this doesn't look possible?
I know this looks like related with polimorfizm. But I wonder somethink like about it;
public Interface ISupClass<E>
call(E type)
...
public class NormalClass implements ISupClass<Boolen.FALSE>
...
public class DailyClass implements ISupClass<Boolen.TRUE>
...
public void call(int type, boolean isDaily){
supClass.call(isDaily);
(In case I understood what is the question)
This is the point of using interfaces. Simply do something like this:
public class Example {
public static interface ISupClass {
void doSomething();
}
public static class NormalClass implements ISupClass {
#Override
public void doSomething() {
System.out.println("I am a normal class.");
}
}
public static class DailyClass implements ISupClass {
#Override
public void doSomething() {
System.out.println("I am a daily class.");
}
}
public static void doSomething(ISupClass clazz) {
clazz.doSomething();
}
public static void main(String[] args) {
doSomething(new DailyClass());
doSomething(new NormalClass());
}
}
So, in your case instead of passing boolean isDaily, pass argument ISupClass in call method.
public void call(int type, ISupClass caller) {
caller.call();
}
Now, generics is a totally different story and I am not able to see how it is related to the question.
From what I understand, public void call(int type, boolean isDaily){...} is an orchestrator/mediator method that manipulates the one or the other instance according to the flags received in the parameters.
In this case, why not use a Map<Boolean, INormalClass> to store the two instances in a way where you can retrieve them from a boolean key :
Map<Boolean, INormalClass> map = new HashMap<>();
map.put(Boolean.TRUE, new DailyClass());
map.put(Boolean.FALSE, new NormalClass());
//...
public void call(int type, boolean isDaily){
INormalClass obj = map.get(isDaily);
if(type == 0) {
obj.call();
}
if(type == 1) {
obj.call1();
}
}
You could add default method to the interface:
public interface ISupClass {
default void call(int type) {
if (type == 0) {
call();
} else if(type == 1) {
call1();
}
}
void call();
void call1();
}
It leads you to following code:
public static void call(int type, boolean isDaily) {
if (isDaily) {
dailyClass.call(type);
} else {
normalClass.call(type);
}
}
I am trying to solve statediagram exercise, but still have not understood why my code does not work.
I chave already cheked all possible code examles of code, but have not understood why mine version does not pass any tests.May be I chve some sort of small mistake which not easy to see. Below I provide my code, test semples and digramms I have.
https://drive.google.com/open?id=1SQAiwUBo1OwI-QKksxciDS7dEdKGS6dn [1]
https://drive.google.com/open?id=1JhdScK7t1XmNc3eLT7hSGpwyYDLWl46T [2]
public class GarageDoor {
private Motor motor;
private DoorState currentState;
public GarageDoor() {
this.setState(new Closed(this));
//currentState=new Closed(this);
}
public void openDoor(){
currentState.openDoor();
}
public void stopper(){
currentState.stopper();
}
public void closeDoor(){
currentState.closeDoor();
}
public Motor getMotor(){
return this.motor;
}
private void setState(DoorState ds){
this.currentState=ds;
}
public abstract class DoorState{
public abstract void openDoor();
public abstract void closeDoor();
public abstract void stopper();
}
public class Closed extends DoorState{
private GarageDoor garageDoor;
public Closed(GarageDoor garageDoor){
this.garageDoor=garageDoor;
}
#Override
public void openDoor() {
garageDoor.setState(new Opening(garageDoor));
garageDoor.getMotor().upwards();
}
#Override
public void closeDoor() {
throw new IllegalStateException();
}
#Override
public void stopper() {
throw new IllegalStateException();
}
}
}
Actually I cann not execute main()
public static void main(String[] args){
//Motor motor=new Motor();
GarageDoor gd=new GarageDoor();
gd.openDoor();
}
I don't see that you're setting motor anywhere, so in Closed.openDoor, when you call garageDoor.getMotor().upwards() you'll get a NullPointerException.
Also, I see that you're passing GarageDoor in to the Closed state and then calling garageDoor.setState. Consider just returning the next state from each DoorState method.
1) Try having GarageDoor extend DoorState, seems to override the same methods.
2) Nowhere in your code do you actually create the Motor in the GarageDoor class.
You need to initiate the Motor, e.g:
public GarageDoor() {
this.motor = new Motor();
}
Hi ive been reading on some similar topics here but none of them answer my question. Some say you cant even do this which is not a good thing since I cant finnish my course in that case.
Heres som simple code. Think of each block as a separate class.
public interface Interface {
void printMessage(String meddelande);
}
public class Model implements Interface {
String message = "hej!";
public static void main(String[] args) {
Model model1 = new Model();
View view1 = new View();
model1.printMessage(model1.message); //Ska jag anropa funktionen såhär ens?
}
public void printMessage(String str) {
}
}
public class View implements Interface {
printMessage(String str) {
}
}
So, how is it now possible to tel the view to print this string from the model class without the classes knowing about each other? Its not allowed to send a reference of the model-objekt to the view-object. ; (
Define an Interface:
public interface MyInterface {
void printMessage(String str);
}
Define a class that can trigger the notification:
public class ClassNotifier {
MyInterface mInterface;
public ClassNotifier(MyInterface mInterface) {
this.mInterface = mInterface;
}
public void triggerTheMsg(String msg) {
if (mInterface != null) {
mInterface.printMessage(msg);
}
}
}
Define a class that will be informed:
public class InformedClass implements MyInterface {
public static void main(String[] args) throws Exception {
InformedClass c = new InformedClass();
ClassNotifier cn = new ClassNotifier(c);
}
#Override
public void printMessage(String newMsg) {
System.out.println("A new msg is here: " + newMsg);
}
}
How does it works?:
this is named a callback parttern, the class ClassNotifier has a reference to the interface MyInterface, which is impl. by Informed class to, so every time the ClassNotifier calls the method printMessage, the method printMessage in the class Informed will be triggered too.
I advice you to use dependency injection, for example:
public class Model {
String message = "hej!";
Interface printer;
public void Model(Interface printer) {
printer = printer;
}
public static void main(String[] args) {
Model model1 = new Model(new View());
model1.printMessage(model1.message);
}
public void printMessage(String str) {
printer.printMessage(str);
}
}
I want to override method from class that's already assigned to a variable.
For example:
inventory = new Inventory( );
/* Some code here that changes how inventory
must behave or whatever */
inventory
{
#Override ...
}
Is it possible ???
Maybe you think of something like this (instead of the null-if you could implement a default strategy to make it more clean):
public interface Strategy {
public void doSomething();
}
public class Inventory {
Strategy strategy;
public Inventory() {
// ...
}
public void doSomething() {
if (strategy == null) {
System.out.println("strategy is empty");
} else {
strategy.doSomething();
}
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
Then this
Inventory inventory = new Inventory();
inventory.doSomething();
inventory.setStrategy(new Strategy() {
#Override
public void doSomething() {
System.out.println("strategy is now something different");
}
});
inventory.doSomething();
shows this:
strategy is empty
strategy is now something different
For a more elaborated version you can take a look at the strategy pattern.
Composition would definitely help here. Rather than overriding a method to change the behavior of Inventory, pass it the method:
class Inventory {
private MyMethod method;
public void setMethod(MyMethod method) {
this.method = method;
}
public void doSomething() {
method.doSomething();
}
}
interface MyMethod {
void doSomething();
}
You can now switch the implementation of MyMethod via setMethod:
Inventory inv = new Inventory();
//...
inv.setMethod(() -> {
//write method here
});
If you aren't using Java 8, you'll have to subclass MyMethod:
inv.setMethod(new MyMethod() {
public void doSomething() {
}
});