I have some small logging system and it can process Strings, which is all working fine.
Now I want to add the ability to signal that I want a new line, and due to my structure I think it is best to use a special flag, some example code:
public class BaseLogger implements Runnable, LogConsumer {
//....
private final BlockingQueue<String> queue;
//....
#Override
public void run() {
while (running) {
try {
if (consumers.isEmpty()) {
synchronized(consumersEmptyLock) {
consumersEmptyLock.wait();
}
}
String message = queue.take();
for (LogConsumer consumer : consumers) {
consumer.consume(message);
}
} catch (InterruptedException ex) {
handleInterrupt();
}
if (requestShutdown && queue.isEmpty()) {
running = false;
}
}
}
public void log(String message) {
if (message == null) {
throw new IllegalArgumentException("customlogger.CustomLogger.log: message == null");
}
queue.offer(message);
}
So now I want to add an enum, let's say LogFlagEnum, which includes a flag called NEW_LINE.
However currently my queue is of type String, and I would like it to include both String (or perhaps T for a more general answer) and LogFlagEnum.
I know I could use Object as type, but that is not the smallest possible type and definatey not safe and what I want.
What would be the best way to implement the specified behaviour?
Solution 1: use Object. It's no big deal since it's just internal implementation.
Solution 2: use CharSequence; have the enum implement CharSequence. Not exactly very helpful. But in general CharSequence is better than String for accepting text arguments.
Solution 3: every problem in Java can be solved by introducing a new type. You queue can be a queue of LogEntry's, and LogEntry can contain String/enum/whatever.
Related
I have the following interface with two implementations:
public interface Parser {
void parse();
boolean canParse(String message);
}
class StackParser implements Parser {
public void parse(){
System.out.println("Parsing stackoverflow");
}
public boolean canParse(String message){
return message.equals("stackoverflow");
}
}
class YoutubeParser implements Parser {
public void parse() {
System.out.println("Parsing youtube");
}
public boolean canParse(String message) {
return message.equals("youtube");
}
}
I go to check incoming message and parse "stackoverflow" or "youtube":
public class Main {
private List<Parser> parsers;
public static void main(String[] args) {
new Main().doSomething("youtube");
}
void doSomething(String message){
parsers.stream()
.filter(p -> p.canParse(message))
.forEach(p -> p.parse());
}
}
Okay, pretty good. But what if message is not "stackoverflow" or "youtube"? App will be silent, but I want to send another default message if no matches were found, like "I can't parse this web!".
I know that will not works (even compile), but it's also should print "I can't parse this web" only one time, not for every false condition.
parsers.stream()
.filter(p -> {
if (p.canParse(message) == false) {
System.out.println("I can't parse it!");
}
})
.forEach(p -> p.parse());
How can I do it?
This is a perfect example of when to use the Optional#orElse or the Optional#orElseThrow method(s). You want to check if some condition is met so you filter, trying to return a single result. If one does not exist, some other condition is true and should be returned.
try {
Parser parser = parsers.stream()
.filter(p -> p.canParse(message))
.findAny()
.orElseThrow(NoParserFoundException::new);
// parser found, never null
parser.parse();
} catch (NoParserFoundException exception) {
// cannot find parser, tell end-user
}
In case only one parser can parse the message at a time you could add a default parser:
class DefaultParser implements Parser {
public void parse() {
System.out.println("Could not parse");
}
public boolean canParse(String message) {
return true;
}
}
And then use it via
// make sure the `DefaultParser` is the last parser in the `parsers`
parsers.stream().filter(p -> p.canParse(message)).findFirst().get().parse();
or alternatively drop the DefaultParser and just do
Optional<Parser> parser = parsers.stream().filter(p -> p.canParse(message)).findFirst();
if (parser.isPresent()) {
parser.get().parse();
} else {
// handle it
}
You can use simply a forEach if-else inside
parsers.forEach(p -> {
if (!p.canParse(message)) {
System.out.println("I can't parse it!");
} else {
p.parse();
}
});
That's a pretty interesting question, which fortunately I had to face some time ago.
Mi approach consisted on declaring a list of Supplier<T> which would be iterated only if there's and exception thrown (the intention of this approach was to retrieve data from DB based on the parameters given, so I would be able to search by id or by an instance).
import java.util.function.Supplier;
public class AbstractFacadeUtil {
public <R> R tryOr(Supplier<R>...fns) {
R result = null;
boolean success = false;
int i = 0;
while (!success && i < fns.length) {
Supplier<R> fn = fns[i++];
try {
result = fn.get();
success = true;
} catch (Exception e) {
}
}
if (!success) {
throw new RuntimeException(new Exception(String.format("[%s] Couldn't find a successful method to apply\"", this.getClass())));
}
return result;
}
}
Some notes:
I'd used Supplier<T> because it's body didn't contain anything that would throw an undeclared exception which, otherwise, would be needed to use Callable<T> instead.
Yeah, could have given it a better name though.
Maybe an Iterator<T> would make that piece of code more understandable and clean.
In your specific case, I'd use Jason's approach by adding a Supplier<T> at the end of the list that would throw an NoParserFoundException
[EDIT]
Also, you should iterate the List<Supplier<T>> or List<Callable<T>> wheter the Parser can't parse and it throws an CantParseException.
So, as you see, exceptions can help a lot even I'm not sure this would be the most efficient or expert approach.
Hope it helps you.
[EDIT2]
This is an example of how I implemented the solution given above.
Ok, I'm gonna say it. Look at every solution posted - what do you think? Are they neat, clean code that you would expect from functional approach?
Nope, why? Because the design is wrong, it doesn't fit functional approach.
Fix the design:
get rid of void return type (brr)
don't overuse methods like canDoSomething (treat them like isPresent in Optional - it's there for extreme cases, mostly technical, not business code)
look into VAVR (or similar library) - classes like Try, Either etc.
Solution will come naturally then and in every case - not only this specific one you posted here.
As SOLID principles say, it's better to remove switch conditions by converting them to classes and interfaces.
I want to do it with this code:
Note: This code is not real code and I just put my idea into it.
MessageModel message = getMessageFromAnAPI();
manageMessage(message);
...
void manageMessage(MessageModel message){
switch(message.typeId) {
case 1: justSave(message); break;
case 2: notifyAll(message); break;
case 3: notify(message); break;
}
}
Now I want to remove switch statement. So I create some classes for it and I try to implement a polymorphism here:
interface Message{
void manageMessage(MessageModel message);
}
class StorableMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
justSave(message);
}
}
class PublicMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notifyAll(message);
}
}
class PrivateMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notify(message);
}
}
and then I call my API to get my MessageModel:
MessageModel message = getMessageFromAnAPI();
Now my problem is here. I have my model and I want manage it using my classes. As SOLID examples, I should do something like this:
PublicMessage message = new Message();
message.manageMessage(message);
But how can I know which type is related to this message to make an instance from it(PublicMessage or StorableMessage or PrivateMessage)?! Should I put switch block here again to do it or what?
You can do this:
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
This will remove your switch to
Consumer<Message> consumer = handlers.get(message.typeId);
if (consumer != null) { consumer.accept(message); }
Integration Operation Segregation Principle
You should of course encapsulate this:
class MessageHandlingService implements Consumer<MessageModel> {
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
public void accept(MessageModel message) {
Consumer<Message> consumer = handlers.getOrDefault(message.typeId,
m -> throw new MessageNotSupportedException());
consumer.accept(message);
}
}
with your client code
message = getMessageFromApi();
messageHandlingService.accept(message);
This service is the "integration" part (as opposed to the "implementation": cfg Integration Operation Segregation Principle).
With a CDI framework
For a production environment with a CDI framework, this would look something like this:
interface MessageHandler extends Consumer<MessageModel> {}
#Component
class MessageHandlingService implements MessageHandler {
Map<Integer,MessageHandler> handlers = new ConcurrentHashMap<>();
#Autowired
private SavingService saveService;
#Autowired
private NotificationService notificationService;
#PostConstruct
public void init() {
handlers.put(1, saveService::save);
handlers.put(2, notificationService::notifyAll);
handlers.put(3, notificationService::notify);
}
public void accept(MessageModel m) { // as above }
}
Behavior can be changed at Runtime
One of the advantages of this vs the switch in #user7's answer is that the behavior can be adjusted at runtime. You can imagine methods like
public MessageHandler setMessageHandler(Integer id, MessageHandler newHandler);
which would install the given MessageHandler and return the old one; this would allow you to add Decorators, for example.
An example for this being useful is if you have an unreliable web service supplying the handling; if it is accessible, it can be installed as a handlelr; otherwise, a default handler is used.
You can use a factory in this case to get the instance of Message. The factory would have all instances of Message and returns the appropriate one based on the MessageModel's typeId.
class MessageFactory {
private StorableMessage storableMessage;
private PrivateMessage privateMessage;
private PublicMessage publicMessage;
//You can either create the above using new operator or inject it using some Dependency injection framework.
public getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return storableMessage;
case 2: return publicMessage;
case 3: return privateMessage
default: //Handle appropriately
}
}
}
The calling code would look like
MessageFactory messageFactory; //Injected
...
MessageModel messageModel = getMessageFromAnAPI();
Message message = messageFactory.getMessage(messageModel);
message.manageMessage(messageModel);
As you can see, this did not get rid of the switch entirely (and you need not as using switch is not bad in itself). What SOLID tries to say is to keep your code clean by following SRP (Single Responsibility Principle) and OCP (Open-Closed Principle) here. What it means here is that you code shouldn't have the actual processing logic to handle for each typeId in one place.
With the factory, you have moved the creation logic to a separate place and you have already moved the actual processing logic to respective classes.
EDIT:
Just to reiterate - My answer focuses on the SOLID aspect of the OP. By having separate handler classes (an instance of Message from the OP) you achieve the SRP. If one of the handler classes changes, or when you add a new message typeId (message.typeId) (i.e, add a new Message implementation) you need not modify the original and hence you achieve OCP. (On assumption that each of these does not contain trivial code). These are already done in the OP.
The real point of my answer here is to use a Factory to get a Message. The idea is to keep the main application code clean and limit the usages of switches, if/else and new operators to instantiation code. (Similar to #Configuration classes/ the classes that instantiate Beans when using Spring or Abstract modules in Guice). The OO principles do not say using switches are bad. It depends on where you use it. Using it in the application code does violate the SOLID principles and that is what I wanted to bring out.
I also like the idea from daniu# to use a functional way and the same can even be used in the above factory code (or can even use a simple Map to get rid of the switch).
The main point here is that you separate instantiation and configuration from execution.
Even with OOP we cannot avoid to distinguish between different cases using if/else cascades or switch statements. After all we have to create instances of specialized concrete classes.
But this should be in initialization code or some kind of factory.
Within the business logic we want to avoid if/else cascades or switch statements by calling generic methods on interfaces where the implementer know better themselves how to behave.
The usual clean code approach is for the MessageModel to contain its behavior.
interface Message {
void manage();
}
abstract class MessageModel implements Message {
}
public class StoringMessage extends MessageModel {
public void manage() {
store();
}
}
public class NotifyingMessage extends MessageModel {
public void manage() {
notify();
}
}
Your getMessageFromApi then returns the proper type, and your switch is
MessageModel model = getMessageFromApi();
model.manage();
This way, you essentially have the switch in the getMessageFromApi() method because it has to decide which message to generate.
However, that is fine because it does fill the message type id anyway; and the client code (where your switch currently resides) is resistent to changes to the messages; ie adding another message type will be be handled correctly.
The real problem you have is that MessageModel isn't polymorphic. You need to convert the MessageModels to a polymorphic Message class, but you shouldn't put any of the logic of what to do with the messages in this class. Instead, it should contain the actual contents of the message, and use the visitor pattern, as shown in Eric's Answer, so that other classes can operate on a Message. You don't need to use an anonymous Visitor; you can create implementing classes like a MessageActionVisitor.
To convert MessageModels to various Messages, you can use a factory, as shown in user7's answer. In addition to selecting which type of Message to return, the factory should fill in the fields of each type of Message using the MessageModel.
You can use the Factory Pattern. I would add an enum which has the values:
public enum MessageFacotry{
STORING(StoringMessage.TYPE, StoringMessage.class),
PUBLIC_MESSAGE(PublicMessage.TYPE, PublicMessage.class),
PRIVATE_MESSAGE(PrivateMessage.TYPE, PrivateMessage.class);
Class<? extends Message> clazz;
int type;
private MessageFactory(int type, Class<? extends Message> clazz){
this.clazz = clazz;
this.type = type;
}
public static Message getMessageByType(int type){
for(MessageFactory mf : values()){
if(mf.type == type){
return mf.clazz.newInstance();
}
}
throw new ..
}
}
Then you can call the static method of that enum and create an instance of the Message you want to manage.
You can use the Factory pattern and Visitor pattern together.
you can create a factory like this:
class MessageFactory {
public Message getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return new StorableMessage((MessageModelType1) message);
case 2: return new PrivateMessage((MessageModelType2) message);
case 3: return new PublicMessage((MessageModelType3) message);
default: throw new IllegalArgumentException("unhandled message type");
}
}
}
and declare your messages like this:
interface Message {
void accept(Visitor visitor);
}
class StorableMessage implements Message {
private final MessageType1 message;
public StorableMessage(MessageModelType1 message) {
this.message = message;
}
#Override
public <Result> Result accept(Visitor<Result> visitor) {
return visitor.visit(this);
}
public MessageModelType1 getMessage() {
return message;
}
}
class PublicMessage implements Message {
...
}
class PrivateMessage implements Message {
...
}
and declare a Visitor like this:
interface Visitor {
void visit(StorableMessage message);
void visit(PublicMessage message);
void visit(PrivateMessage message);
}
and replace your switch statements with this:
Message message = ....;
message.accept(new Visitor() {
#Override
public void visit(StorableMessage message) {
justSave(message.getMessage());
}
#Override
public void visit(PublicMessage message) {
notifyAll(message.getMessage());
}
#Override
public void visit(PrivateMessage message) {
notify(message.getMessage());
}
});
If you want, instead of writing an anonymous class, you can create a class MessageModelFactory that has a private Visitor, and use that instead. in that case, it might be better to make the Visitor interface like this:
interface Visitor<Result> {
Result visit(StorableMessage message);
Result visit(PublicMessage message);
Result visit(PrivateMessage message);
}
Currently I have a method to consume events of a Queue. Based on the type I call the appropriate method to handle it.
private void consumeQueue() {
MyQueue myQueue = MyQueue.getInstance();
Iterator mIterator = myQueue.iterator();
while (mIterator.hasNext()) {
Object mEvent = null;
try {
mEvent = mIterator.next();
mIterator.remove();
} catch (NoSuchElementException e) {
return;
}
if (mEvent instanceof EventOne)
handleOne((EventOne) mEvent);
else if (mEvent instanceof EventTwo)
handleTwo((EventTwo) mEvent);
...
}
}
Let's suppose that elsewhere the developer enqueue a new type of event, let's call it EventThree. Doing it in this way I can't be sure that the developer will handle EventThree's consumption properly.
Is there any pattern so I can force (at compile time) the developer, to handle EventThree's consumption?
As far as I understand your MyQueue class implements Queue interfance. You should never use raw types in your code. Consider using your MyQueue as a generic class with some type parameter:
MyQueue<EventOne> myQueue = MyQueue.getInstance();
Ofc you'll have to change getInstance() method too. An elegant solution may look like:
<T> MyQueue<T> getInstance(Class<T> clazz) {
if (clazz == EventOne.class) {
// ...
} else if (clazz == EventTwo.class) {
// ...
}
}
P.S. Unfortunately you can't define two getInstance() methods with different Queue type parameter because of Java's type erasure.
This question already has answers here:
How to call a method stored in a HashMap? (Java) [duplicate]
(3 answers)
Closed 8 years ago.
I have read this question and I'm still not sure whether it is possible to keep pointers to methods in an array in Java. If anyone knows if this is possible (or not), it would be a real help. I'm trying to find an elegant solution of keeping a list of Strings and associated functions without writing a mess of hundreds of if statements.
Cheers
Java doesn't have a function pointer per se (or "delegate" in C# parlance). This sort of thing tends to be done with anonymous subclasses.
public interface Worker {
void work();
}
class A {
void foo() { System.out.println("A"); }
}
class B {
void bar() { System.out.println("B"); }
}
A a = new A();
B b = new B();
Worker[] workers = new Worker[] {
new Worker() { public void work() { a.foo(); } },
new Worker() { public void work() { b.bar(); } }
};
for (Worker worker : workers) {
worker.work();
}
You can achieve the same result with the functor pattern. For instance, having an abstract class:
abstract class Functor
{
public abstract void execute();
}
Your "functions" would be in fact the execute method in the derived classes. Then you create an array of functors and populate it with the apropriated derived classes:
class DoSomething extends Functor
{
public void execute()
{
System.out.println("blah blah blah");
}
}
Functor [] myArray = new Functor[10];
myArray[5] = new DoSomething();
And then you can invoke:
myArray[5].execute();
It is possible, you can use an array of Method. Grab them using the Reflection API (edit: they're not functions since they're not standalone and have to be associated with a class instance, but they'd do the job -- just don't expect something like closures)
Java does not have pointers (only references), nor does it have functions (only methods), so it's doubly impossible for it to have pointers to functions. What you can do is define an interface with a single method in it, have your classes that offer such a method declare they implement said interface, and make a vector with references to such an interface, to be populated with references to the specific objects on which you want to call that method. The only constraint, of course, is that all the methods must have the same signature (number and type of arguments and returned values).
Otherwise, you can use reflection/introspection (e.g. the Method class), but that's not normally the simplest, most natural approach.
I found the reflection approach the cleanest -- I added a twist to this solution since most production classes have nested classes and I didn't see any examples that demonstrates this (but I didn't look for very long either). My reason for using reflection is that my "updateUser()" method below had a bunch of redundant code and just one line that changed (for every field in the user object) in the middle that updated the user object:
NameDTO.java
public class NameDTO {
String first, last;
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
}
UserDTO.java
public class UserDTO {
private NameDTO name;
private Boolean honest;
public UserDTO() {
name = new NameDTO();
honest = new Boolean(false);
}
public NameDTO getName() {
return name;
}
public void setName(NameDTO name) {
this.name = name;
}
public Boolean getHonest() {
return honest;
}
public void setHonest(Boolean honest) {
this.honest = honest;
}
}
Example.java
import java.lang.reflect.Method;
public class Example {
public Example () {
UserDTO dto = new UserDTO();
try {
Method m1 = dto.getClass().getMethod("getName", null);
NameDTO nameDTO = (NameDTO) m1.invoke(dto, null);
Method m2 = nameDTO.getClass().getMethod("setFirst", String.class);
updateUser(m2, nameDTO, "Abe");
m2 = nameDTO.getClass().getMethod("setLast", String.class);
updateUser(m2, nameDTO, "Lincoln");
m1 = dto.getClass().getMethod("setHonest", Boolean.class);
updateUser(m1, dto, Boolean.TRUE);
System.out.println (dto.getName().getFirst() + " " + dto.getName().getLast() + ": honest=" + dto.getHonest().toString());
} catch (Exception e) {
e.printStackTrace();
}
}
public void updateUser(Method m, Object o, Object v) {
// lots of code here
try {
m.invoke(o, v);
} catch (Exception e) {
e.printStackTrace();
}
// lots of code here -- including a retry loop to make sure the
// record hadn't been written since my last read
}
public static void main(String[] args) {
Example mp = new Example();
}
}
You are right that there are no pointers in java because a reference variables are the same as the & syntax in C/C++ holding the reference to the object but no * because the JVM can reallocate the heap when necessary causing the pointer to be lost from the address which would cause a crash. But a method is just a function inside a class object and no more than that so you are wrong saying there are no functions, because a method is just a function encapsulated inside an object.
As far as function pointers, the java team endorses the use of interfaces and nested classes which all fine and dandy, but being a C++/C# programmer who uses java from time to time, I use my Delegate class I made for java because I find it more convenient when I need to pass a function only having to declare the return type of the method delegate.
It all depends on the programmer.
I read the white pages on why delegates are not support but I disagree and prefer to think outside the box on that topic.
Okay guess this question looks a lot like:
What is the best way to replace or substitute if..else if..else trees in programs?
consider this question CLOSED!
I would like to refactor code which looks something like this:
String input; // input from client socket.
if (input.equals(x)) {
doX();
} else if (input.equals(y)) {
doY();
} else {
unknown_command();
}
It is code which checks input from socket to perform some action, but I don't like the if else construction because every time a new command is added to the server (code) a new if else has to be added which is ugly. Also when deleting a command the if else has to be modified.
Collect those commands in a Map<String, Command> where Command is an interface with an execute() method.
Map<String, Command> commands = new HashMap<String, Command>();
// Fill it with concrete Command implementations with `x`, `y` and so on as keys.
// Then do:
Command command = commands.get(input);
if (command != null) {
command.execute();
} else {
// unknown command.
}
To get a step further, you could consider to fill the map dynamically by scanning for classes implementing a specific interface (Command in this case) or a specific annotation in the classpath. Google Reflections may help lot in this.
Update (from the comments) You can also consider combining the answer of Instantsoup with my answer. During the buildExecutor() method, first get the command from a Map and if the command doesn't exist in Map, then try to load the associated class and put it in the Map. Sort of lazy loading. This is more efficient than scanning the entire classpath as in my answer and creating it everytime as in Instantsoup's answer.
One way could be to have an interface ICommand that is the general contract for a command, e.g.:
public interface ICommand {
/** #param context The command's execution context */
public void execute(final Object context);
public String getKeyword();
}
And then you could use Java's SPI mechanism to auto-discover your various implementations and register them in a Map<String,ICommand> and then do knownCommandsMap.get(input).execute(ctx) or something alike.
This practically enables you to decouple your service from command implementations, effectively making those pluggable.
Registering an implementation class with the SPI is done by adding a file named as the fully qualified name of your ICommand class (so if it's in package dummy the file is going to be META-INF/dummy.ICommand within your classpath), and then you'll load and register them as:
final ServiceLoader<ICommand> spi = ServiceLoader.load(ICommand.class);
for(final ICommand commandImpl : spi)
knownCommandsMap.put(commandImpl.getKeyword(), commandImpl);
How about interfaces, a factory, and a little reflection? You will still need to handle exceptions on bad input, but you would always need to do this. With this method, you just add a new implementation of Executor for a new input.
public class ExecutorFactory
{
public static Executor buildExecutor(String input) throws Exception
{
Class<Executor> forName = (Class<Executor>) Class.forName(input);
return (Executor) executorClass.newInstance();
}
}
public interface Executor
{
public void execute();
}
public class InputA implements Executor
{
public void execute()
{
// do A stuff
}
}
public class InputB implements Executor
{
public void execute()
{
// do B stuff
}
}
Your code example then becomes
String input;
ExecutorFactory.buildExecutor(input).execute();
Building the Command patten upon an enum class can reduce some of the boilerplate code. Let's assume that x in input.equals(x) is "XX" and y in input.equals(y) is "YY"
enum Commands {
XX {
public void execute() { doX(); }
},
YY {
public void execute() { doY(); }
};
public abstract void execute();
}
String input = ...; // Get it from somewhere
try {
Commands.valueOf(input).execute();
}
catch(IllegalArgumentException e) {
unknown_command();
}
You say that you're processing input from a socket. How much input? How complex is it? How structured is it?
Depending on the answers to those questions, you might be better off writing a grammar, and letting a parser generator (eg, ANTLR) generate the input-processing code.