I have an xml file that contains data I want to parse and read into my program so i can instantiate a class.
The problem is, which class i want to instantiate wont be known until runtime.
My xml will be a little like below.
<dataitem class="FooClass">
<dataitem class="BarClass">
Classes will all share a common interface.
At the moment i have Factory doing something like below.
public class FooBarFactory {
FooBarInterface makeClass(String s){
if(s.equals("FooClass")){
return new FooClass();
}
if(s.equals("BarClass")){
return new BarClass();
}
}
In reality, there are a great many potential classes the Factory could return. Is there a way to get this sort of behaviour without having to use a conditional statement for each potential class it could be? If not, is my thinking correct or is there a better way of doing this?
public class FooBarFactory {
FooBarInterface makeInstance(String s) {
return Class.forName(s).newInstance();
}
}
I didn't show it, but you will need to handle some checked exceptions such as ClassNotFoundException, IllegalAccessException, and InstantiationException.
Related
Currently, I try to design some things with OO principles in mind. So let's say, before processing user input, I need to validate it. According to OO, a separate Validator class would be the correct way. This would look as follows:
public class Validator{
public void validate(String input) throws ValidationException{
if (input.equals("")) throw new ValidationException("Input was empty");
}
}
Then, my processing class, which got the validator object before via dependency injection would call validator.validate(input)
A good point about this design is, that
My processing class can get a mock for the validator via DI which makes testing easier
The Validator class can be tested independently
However, my doubts are in the design of the Validator. According to OO, it misses some kind of state. With this design, it is as util class and the validate method could be static. And I read a lot of times that (static) Util classes are bad OO design. So, how can this be done with more OO while keeping the two advantages I mentioned?
PS.: Maybe, OO is simply a bad solution for this kind of problem. However, I would like to see how the OO solution would look like and form my own opinion.
The validator in your example doesn't have a state (and doesn't need any), but another validator could require one (say with a format):
Example:
public class RegExValidator {
private Pattern pattern;
public RegExValidator(String re) {
pattern = Pattern.compile(re);
}
public void validate(String input) throws ValidationException {
if (!pattern.matcher(input).matches()) {
throw new ValidationException("Invalid syntax [" + input + "]");
}
}
}
Concentrating on the OOP aspect of your question (rather than the question if an Exception is the correct way to handle your validation):
Why have a single validator?
interface Validator<T> {
void validate(T toValidate) throws ValidationException;
}
would enable you to write classes that can validate any class T and be very testable. Your validator would look like this:
class EmptyStringValidator implements Validator<String> {
public void validate(String toValidate) {
if(toValidate == null || toValidate.isEmpty()) throw new ValidationException("empty!!!");
}
}
and you could test it very easily.
In fact, if you're using Java 8, this would be a functional interface, so a single utility class could host several validators:
class ValidationUtil {
public static void emptyString(String val) // same code as above
}
and ValidationUtil::emptyString would implement Validator<String>.
You would combine several validators with a composite pattern.
You could also have a validator with a state if that's what you need...
class ListIsSortedValidator implements Validator<Integer> {
private int lastInt = Integer.MIN_VALUE;
public void validate(Integer val) throw ValidationException {
if (val < lastInt) throw new ValidationException("not sorted");
lastInt = val;
}
}
That you could use to for instance validate a list:
List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);
It depends on the circumstances of course, but I think your instinct is correct. This design could be more Object-Oriented.
It is not just that Validator has no state, which is a purely mechanical indicator that it is likely not a correct abstraction, but the name itself tells us something. Usually Validator (or even EmptyStringValidator) is not part of the problem domain. It is always a bad sign when you have to create something purely technical (although sometimes it is the less of two evils).
I assume you are not writing a web-framework, you are trying to write an application that has some domain. For example it has user registration. Then, RegistrationForm is part of the problem domain. Users know about the "registration form", you can talk about it and they will know what you mean.
In this case, an Object-Oriented solution for validation would be that this object is responsible for the validation of itself during the "submitting" of itself.
public final class RegistrationForm extends Form {
...
#Override
public void submit() {
// Do validation here
// Set input fields to error if there are problems
// If everything ok do logic
}
}
I know this is not the solution normally seen or even supported by web-frameworks. But it is how an Object-Oriented solution would look like.
The two important points to always keep in mind are:
Don't "get" data from objects, ask them to do something instead. This is as applicable to UI code as anything else.
OO makes sense when the objects focus on meaningful things, i.e. the problem domain. Avoid over-representing technical (unimportant) objects, like Validator (if that's not your application's domain).
As we all know exception is a by default class and exception class extends Throwable.
My question is: why exception is not a interface ?
if we will try to mold exception class as interface it will show error. i tried it out but still i am not able to find a exact reason for the same.
this is a code I tried:
Interface:
package com.prg;
import com.thed.util.CustomException ;
public interface ExceptionInterface extends Throwable{
public String sayHello() throws CustomException {
return null;
}
}
Class:
package com.prg;
import com.thed.util.CustomException ;
public class ExceptionCheck implements ExceptionInterface {
public String sayHello() {
return "Hey";
}
public ExceptionCheck() throws CustomException {
System.out.println("hi");
}
public static void main (String[] args) throws CustomException {
System.out.println("how are you");
throw new ExceptionInterface({
public String sayHello() { return "Hey"; }
});
}
}
If i am changing interface to class then it is not showing exception which is expected. but why not interface this is my question ?
Simple: because there is quite a lot of implementation code to be found within the Throwable class which is the base of the whole hierarchy. And as one comment reminds us: there is also a lot of exception related code backed into the native parts of the JVM - and it would be probably very hard if that code had to deal with arbitrary objects implementing an Exception interface.
There is no point in using interfaces when you want to give a core library element to your users that includes implementation.
( keep in mind that default methods - aka method bodies - weren't allowed in Java until Java8 !)
Beyond that: interfaces are useful to allow different "views" on classes. In other words: Integer for example can be seen as Comparable. There might be situations where it is perfectly fine to only address an Integer object as a Comparable. But the true essential nature of Integer is still: it is a class representing a whole number of a certain range.
Now think about exceptions! What would be the conceptual "sense" in having public class Foo implements Exception? What would Foo be about "without" that exception view?! In other words: exceptions are also conceptually "important" enough to stand as distinct classes!
Keep in mind that classes and interfaces exist to model abstractions. Maybe I am just not creative enough - but I do not see how something could be a Foo object - but also, if required be an exception.
Finally: a class is a class, and an interface is an interface. Those are different things. And the only relation that is allowed is: classes extend classes, and can implement interfaces. Interfaces can only extend other interfaces. That is simply how the Java language is designed - and there is no way of doing what you code implies you want to do.
I have a design question.
I have an interface that read XML. Each implementer class read different XML and I want a way to identify which implementer should I dynamically create for the xml type I get.
The problem is that java interface can't have static members. What is the best way to do it?
Example:
public interface MyXML{
public void readXML(String xml);
public final static String getType();
}
Usage:
func(String xml, String type)
{
MyXML obj;
switch(type)
{
case MyImpl.getType():
obj = new MyImpl();
break;
case MyImpl2.getType():
obj = new MyImpl2();
break;
}
obj.readXML(xml);
}
EDIT:
I'll try to explain better what I want:
I need to know which xml can be read by which implementation and I search for a way to force anyone that implements MyXML to tell which xml it can read so I'll not need to maintain the translation outside in another list or factory.
Java only allow static constants in the interface. In Java 8 you can have also default implementations, but that's a different thing.
One way to solve this is to make getType normal instance method, same as readXML and instantiate implementations in advance, something like this
// somewhere in the constructor or main
List<MyXML> readers = Arrays.asList(new MyImpl1(), new MyImpl2());
public MyXML findReaderForType(String type) {
for (MyXML reader : readers) {
if (reader.getType().equals(type)) {
return reader;
}
}
}
However you need to be careful to design your implementations in the way, so they can be reused.
Another option is to create some sort of static factory, which will contain the equivalent of findReaderForType method. Then the mapping between the type and implementation is contained in this factory class.
Take a look at Factory Design Pattern. The client should call the factory passing the Type, then the factory returns an instance of the correct class:
public class MyFactory {
public MyXML createMyXML(Type type) {
return ...
}
}
This way the client is free from the responsability to know which concrete class needs to be provided.
There's no point in storing implementation types in interface. The interface shouldn't know about implementations. Instead you can store the XML Type in Enum.
enum Type{
TYPE1,
TYPE2;
}
Then you can create a Map<Type, MyXML> variable and add implementations with their corresponding Type in it.
Factory can then be something like:
public MyXml getImplementation(String type){
Type type = Type.valueOf(type);
MyXml impl= implementations.get(type);
if(impl == null){
throw new UnsupportedOperationException();//or whatever ex you see fit
}
return impl;
}
I suggest you design your system around instances, not types themselves.
The application would instantiate all the XML reader types and would query each instance for the type it is in charge of. You can use that to organize the XML readers into a map and retrieve them with no switch or if-statements.
If there are some heavyweight resources associated with an instance in your current design, then change that design such that all the resource acquisition happens later into the object's lifecycle, not at construction time.
If you need several instances of the same reader at once (for example, in a concurrent setting), then use the idea exemplified by java.util.regex.Pattern and its corresponding Matcher. A pattern is a thread-safe factory of single-threaded, disposable matchers.
I have a class that has a method. The method may fail and I want to throw an exception. Is it bad to define the exception class within the namespace of the class whose function is throwing the exception? I haven't seen a lot of examples of this, but it seems like the "right" (i.e. OO) way to do it? Is there a reason I should avoid this pattern and define each custom exception in its own file?
public class Foo
{
void bar() {
// do something and throw BarException if something bad happens
}
public static class BarException extends Exception {
// rest of class definition
}
}
I think it depends on the possible scope of the Exception you're creating. If it will only have to do with Foo, and only Foo, forever, then creating it as a nested class would be good.
Just make sure it makes sense for something calling Bar to say:
catch (Foo.BarException e)
instead of
catch (BarException e)
Else, create it as its own standalone class.
As for the namespace, a Java class could be used for namespacing classes, but generally in Java packages are used for namespacing your classes. I would only use a nested class if there is a very high coupling between the main class and the other class.
I would not use this pattern.
You add more line to class.
This class has more than one concern
and you will get problems, if you want to use the same Exception in another class.
Why do you want to do this? Just, because you don't want to create a new file? ;)
In Java you should only ad one public class in one file. Sometimes I add public interfaces into classes, most for event handling.
class MyEvent {
public void registerHandler(MyEvent.Handler h){
//
}
public interface Handler(){
handle();
}
}
In this case I am absolute sure, there wont be any other class using this Interface.
I have 3 classes:
Error
ShellError
WebError
where
ShellError extends Error
and
WebError extends Error
In ShellError there are fields some of which are optional and others are required. I am building the object in the following manner:
shellError = new ShellError.Builder().setFile(filePattern)
.setHost(host).setPath(path).setSource(file.isSource())
.setJobName(p.getJobName()).build();
Since ShellError extends Error, I further:
shellError.setDescription(msg.toString());
shellError.setExceptionClass("MyEvilException");
shellError.setExceptionMessage("Some clever error message");
shellError.setStacktrace(stack);
So ... why bother with Builder? I like the fact that my build() amongst other things conveniently validates that all fields are set appropriately etc.
I would love it if I could .. build() ShellError and add to it the fields from the Error class.
What i did works.
The question is:
Is there a better way, or does it make sense what I did?
-- EDIT
I updated Builder() to accept some of the parameters which were in Error class before. Now I have
shellError = new ShellError.Builder(exception, "Some description").setFile(filePattern).setHost(host)
.setPath(path).setSource(file.isSource()).
setJobName(p.getJobName()).build();
What do you say? Better? Worse?
The builder pattern, popularized by Josh Bloch, has several benefits, but it doesn't work so elegantly on parent/subclasses, as explained in this discussion by our colleagues in the C# world. The best solution I have seen so far is this one (or a slight variant of it).
Based on the functions you've referenced, this is clearly not the standard java.lang.Error class. Typically builders are used to allow for an immutable object to be easily constructed or to provide functionality similar to "named parameters" in cases where there are lots of configuration / construction parameters.
For this particular case, it would be more sensible if the Error class were immutable after construction, and if these additional setter functions were on the builder instead of on the error class. I don't know how much control you have over any of these classes, but if you can modify them, I would suggest first making the builder support the same setters, so you can do all the configuration at the builder. Then, if it is feasible to do so, you could try removing these setter methods and instead allowing these to be configured from the constructor. If you don't have any control at all over those, you can could potentially extend the builder class with another one which supports these additional methods.
What you did makes sense. It seems like the design of the builder and error classes don't necessarily make a whole lot of sense, forcing you to write code that feels inelegant or inconsistent.
As it was already said, the builder pattern is not something that could organically fit into the existing Java object initialization politics. There are several approaches to achieve the required result. Though, of course, it is always better to avoid any ambiguous practices, it's not always possible. My hack is based on Java reflection API with generics:
abstract public class AbstractClass {
public static class Builder {
public <T extends AbstractClass> T build(Class<T> implementingClass) {
try {
Constructor<T> constructor = implementingClass
.getConstructor(new Class[]{Builder.class});
return constructor.newInstance(this);
} catch (NoSuchMethodException e) {
// TODO handle the exception
} catch (InvocationTargetException | InstantiationException |
IllegalAccessException e) {
// TODO handle the exception
}
}
}
protected AbstractClass(Builder builder) {
}
}
public class ImplementingClass extends AbstractClass {
public ImplementingClass (Builder builder) {
super(builder);
}
}
The initialization:
ImplementingClass instance = new AbstractClass.Builder()
.build(ImplementingClass.class);