requirement is like this: user input is single character followed by an array of integers, such as 'A 1 2', 'B 3 4 5', 'C 1', etc. The single character means which class to construct and integers are input parameter to that constructor. Please note different classes might need different number of integers.
Then we need to write a program to parse user input and create objects accordingly.
My approach was to use regular expression for parsing and hard code which class to call.
But another senior developer said a better idea would be using dependency injection to automatically create objects based on user input. He gave another hint to create an interface and use spring framework dependency injection (not spring boot).
I am still confused how to create beans dynamically in this way. Can anybody help please?
You can create a common interface for the classes that can be created, and a Factory bean that transforms the input.
// common interface
interface MyObject {
void someMethod();
}
class A implements MyObject {
public A(List<Integer> params) { ... }
}
class B implements MyObject {
public B(List<Integer> params) { ... }
}
// parsed data
class Input {
char character;
List<Integer> ints;
// getters, setters
}
interface MyObjectFactory {
public MyObject apply(Input input);
}
#Bean
class MyObjectFactory implements MyObjectFactory {
public MyObject apply(Input input) {
// create object from input, eg switch over input.getCharacter()
};
}
// injected
class MyClientService {
#Autowired
MyObjectFactory objectFactory;
public void doStuff() {
List<Input> parsedInputs = parse(something);
for (Input input : parsedInputs) {
MyObject object = objectFactory.apply(input);
// ...
}
}
}
Related
I have the following POJO using Immutables+Jackson under the hood:
#JsonInclude(JsonInclude.Include.NON_NULL)
abstract class AbstractQueryRequest {
#JsonProperty("reqid")
public abstract String reqid();
#JsonProperty("rawquery")
public abstract String rawquery();
}
At some point I need to build another object based on the fields of the POJO, something along this line:
final HttpUrl.Builder urlBuilder = HttpUrl.parse(cfg.baseUrl()).newBuilder();
urlBuilder.addQueryParameter("reqid", request.reqid())
.addQueryParameter("rawquery", request.rawquery());
It's quite annoying to keep the POJO and this call aligned upon changes, I was wondering if it was possible to access programmatically each JsonProperty instead of typing the string manually.
Note that it is fine to write the getters by hand as I can easily refactor and I have the compiler double checking, but for strings I am worried for people down the line and I would like to "read" them from the POJO class somehow.
You can do it via reflection. You need to take method annotation values which annotated with JsonProperty. But I recommend you to use JsonProperty on fields, not methods.
Here is an example for your current requirement :
public class Main {
public static void main(String[] args) {
AbstractQueryRequest someType = new SomeType();
for(Method method : x.getClass().getSuperclass().getDeclaredMethods()) {
if (method.isAnnotationPresent(JsonProperty.class)) {
JsonProperty annotation = method.getAnnotation(JsonProperty.class);
System.out.println(annotation.value());
}
}
}
}
class SomeType extends AbstractQueryRequest {
#Override
public String reqid() {
return null;
}
#Override
public String rawquery() {
return null;
}
}
Output is :
rawquery
reqid
I would like to implement something like Strategy Pattern. I have generalized logic in Parent method, I need to pass specific logic (with casting etc..) into parent.
I have following classes:
class A{
public Object generateData(Function fetchData, AbstractForm form)
{
List<DataBean> dataBeans = (List<DataBean>) fetchData.apply(form);
//...
}
}
class B extends A{
void someMethod(AbstractForm form){
Function<AbstractForm, List<DataBean>> fetchFunction = new Function<AbstractForm, List<DataBean>>() {
//here goes form specific casting and other data fetch specific logic
return dataBeans;
}
super.generateData(fetchFunction, form);
}
}
Did I get the Idea of function correctly here?
Correct use of the Strategy pattern implies aggregation between a Context (in your case class A) and a Strategy (in your case an implementation of Function).
You can see the relationship in the image below (taken from the Gang of Four book, Design patterns: elements of reusable object-oriented software).
Below I've applied a traditional Strategy pattern approach to your problem. In this case I've made it so that Function.apply(AbstractForm) returns List<DataBean> to remove the need for casting. You could of course use generics to make Function more flexible.
Strategy
public interface Function {
List<DataBean> apply(AbstractForm form);
}
Context
public class A {
private Function fetchData; // strategy
public void setStrategy(Function fetchData) { // method for setting the strategy
this.fetchData = fetchData;
}
// precondition: fetchData != null
public Object generateData(AbstractForm form) {
List<DataBean> dataBeans = fetchData.apply(form); // using the strategy
return null; // whatever you want to return
}
}
In this case, extending class A is not neccessary as we can inject our Strategy (Function) using setStrategy(Function). However, we could always extend A to great an object with a predefined Strategy.
For example:
public class B extends A {
public B() {
setStrategy((form) -> null); // implement your concrete strategy here
}
}
Using a Factory Method
Since a Strategy for fetching the data is likely required and there may be no 'default' to use and may not ever change, the Factory method pattern could be used instead to enforce the creation of a Product (Function). Note class A is now abstract and includes a Factory method createFunction() which is then implemented in the subclasses (e.g. B) to create the Function.
The design for the factory method pattern can be seen in the UML below. In this case our Product is now what was previously our Strategy (Function) and the Creator is class A, with the ConcreteCreator being class B.
Creator
public abstract class A {
private Function fetchData; // product to be used
public class A() {
fetchData = createFunction(); // call factory method
}
protected abstract Function createFunction(); // factory method
// precondition: fetchData != null
public Object generateData(AbstractForm form) {
List<DataBean> dataBeans = fetchData.apply(form); // using the product
return null; // whatever you want to return
}
}
ConcreteCreator
public class B extends A {
#Override
protected Function createFunction() {
return (form) -> null; // return product
}
}
In this case the Product is fixed and not changable, but this could be overcome by mixing the two patterns together and including setStrategy(Function) again from class A in the first example.
Lets say we have to retrive data of class: Trade. This trade class has many parameters like A, B, C....
class A { retrieveTradeDataWithA(); and many more methods which do something }
class B { retrieveTradeDataWithB(); and many more methods which do something }
class LetsSaySomeResource {
#Inject
private A classAInstance;
#Inject
private B classBInstance;
public void getTradeDataBasedOnA(){
classAInstance.retrieveTradeDataWithA();
}
public void getTradeDataBasedOnB(){
classBInstance.retrieveTradeDataWithB();
}
}
Now the requirement is we want to fetch some trade data based on A and B both and later on maybe more classes like A and B will be added to get data based on this. How shall i make the design more flexible?
Like,
public void getDataBasedOnAandB(){
}
Or, later on C class can come, so i dont want to keep injecting filters like A,B....
Can someone help on this?
First create an interface that will define the contract for doing something :
public interface IData {
void doSomething();
}
Then create the concrete implementations to do something :
public class DataA implements IData {
#Override
public void doSomething() {
// TODO Do something for A
}
}
public class DataB implements IData {
#Override
public void doSomething() {
// TODO Do something for B
}
}
And finally a class that will actually do something :
public class DataDAO {
private List<IData> dataList;
public DataDAO(List<IData> dataList) {
this.dataList = dataList;
}
public void doSomething() {
for(IData data : dataList) {
data.doSomething();
}
}
}
Now let's take your use cases :
do something for A :
List<IData> dataAList = new ArrayList<IData>();
dataList.add(new DataA());
DataDAO dataADAO = new DataDAO(dataAList);
dataADAO.doSomething();
do something for A and B :
List<IData> dataAList = new ArrayList<IData>();
dataList.add(new DataA());
dataList.add(new DataB());
DataDAO dataADAO = new DataDAO(dataAList);
dataADAO.doSomething();
It may look something like this:
class LetsSaySomeResource {
#Resource
private Map<String, DataAccessInterface> instanceToDataAccessMapping;
public DateAggregationResult getDataFor(String... instanceNames) {
DataAggregationResult result = new DataAggregationResult(); // some list or whatever
for (String instanceName : instanceNames) {
Data data = instanceToDataAccessMapping.get(instanceName).getData();
/**
* Add this data to aggregation result here
*/
}
return result;
}
}
Try something like the decorator pattern. If your classes will grow over time always based on previous requirements, you could add the additional computations by decorating them.
Your example is still very abstract so it is hard to tell whether your additional classes are interdependent or simply "extended" (a simple inheritance would do).
Or completely decoupled so something like SimY4 did could help (use e.g. a variation of the visitor pattern).
I think template design pattern would be useful here. http://en.wikipedia.org/wiki/Template_method_pattern
you can define your template method in the base class and let the sub classes implementing this class define their own algorithm to do this. Do read the wiki link and you would find your way out.
I have multiple classes whose properties need to be written to a text file. Since each class has different properties each requires a different algorithm to write. I'm trying to use a strategy pattern for this but it doesn't seem to be working out - don't know if this is even the correct pattern to use?
class A
{
void one;
void two;
void three;
}
class B
{
void four;
void five;
void six;
void seven;
}
class C
{
void eight;
void nine;
}
This is where im having trouble with my design, how would I pass the object into the concrete strategy?
class DataParser
{
Object object;
void DataParser(Object object)
{
this.object = object;
parsers.put(new ClassA(), new ClassAParser());
parsers.put(new ClassB(), new ClassBParser());
parsers.put(new ClassC(), new ClassCParser());
}
void writeData()
{
ParserInterface parser = parsers.get(this.object);
/*
* classAParser.setClassA(object);
* classBParser.setClassB(object);
* classCParser.setClassC(object):
*/
parser.write();
}
}
.
interface ParserInterface
{
void write();
void read();
}
.
class ClassAParser()
{
ClassA classA;
void setClassA(ClassA classA)
{
this.classA = classA;
}
void write()
{
PrinterWriter writer = new PrintWriter("ClassA.txt");
writer.printLn(this.classA.getOne() + "|" + this.classA.getTwo() + "|" + this.classA.getThree());
writer.close();
}
void read()
{
}
}
.
class ClassBParser()
{
ClassB classB;
void setClassB (ClassB classB )
{
this.classB = classB ;
}
void write()
{
PrinterWriter writer = new PrintWriter("ClassB.txt");
writer.printLn(this.classB.getFour() + "|" + this.classB.getFive() + "|" + this.classB.getSix() + "|" + this.classB.getSeven());
writer.close();
}
void read()
{
}
}
So then I can just simply do something like this:
class Test()
{
void testClassA()
{
ClassA classA = new ClassA();
classA.setOne("One");
classA.setTwo("Two");
classA.setThree("Three");
DataParser parser = new DataParser(classA);
parser.writeData();
}
}
Then the ClassA.txt should have the following: "one|two|three"
I think the strategy interface might be a little overkill for what you are trying to achieve. An interface will probably get you what you want:
public interface Writable {
void writeTo(PrintWriter writer);
}
class A implements Writable {
String one;
String two;
String three;
public void writeTo(PrintWriter writer) {
// do the writing here
}
}
Repeat for ClassB and ClassC...
Here is a long shot ,
i have seen in your code the following:
parsers.put(new ClassA(), new ClassAParser());
but i cannot find where you declare this variable (i guess is wrong copy-paste)
Anyway, i assume that you use a HashMap because of the method put().
If this is the case you need to implement both equals() and hashCode() in the classes A, B, C.
see here why
Understanding the workings of equals and hashCode in a HashMap
http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html
(in short words if you don't override these methods then the object you pass in the
parsers.get(this.object);
should be the exact same instance with the one of the objects you have putted in your map but in your case it is not)
You can use the same mode as described in Java: If-else instanceof extended classes if you don't want to let your class implements an interface. To factory class you have to pass object to write and where to write.
Another way can be to use a template method pattern in this way:
abstract class ParserReaderWriter implements ParserInterface {
protected abstract String[] getDataToWrite();
protected abstract PrintWriter createWriter();
void write() {
Writer writer = createWriter();
writer.println(StringUtils.join(getDataToWrite(),"|");
writer.close();
}
}
then create a writer for all writer
class AParserReaderWriter extends ParserReaderWriter {
ClassA object;
AParserReaderWriter(ClassA object) {
this.object = object;
}
protected String[] getDataToWrite() {
return new String[]{this.object.getOne(),...};
}
protected PrintWriter createWriter() {
return new PrintWriter("a.txt");
}
}
I don't see the need for a "strategy", here (at least that sounds too heavy-weight for me in this case). Also, I wouldn't "map" anything explicitly here.
So basically I've understood that you'll have objects of the given classes at some time in your application, and then want to create text files in a format defined freely by yourself. This is perfectly valid as a requirement, so I won't point you to any conventions or tools, here. However I also understand that you don't want to do the "serialization" individually within each of the classes, but rather use one (custom) "serializer", probably application-wide. This is where my suggestion differs from other answers.
The method which will actually create the text files needs at least these pieces of information:
the object(s) actually containing the property values
what properties there are (or even: which ones are actually to be considered)
the (base) name of the file to write to - and the character encoding to use, or, more generally, a Writer, or whatever fits your specific requirements on this aspect.
My personal approch would thus be to implement a Util method being as specific as allowed in your case, and as generic as needed to avoid duplicate code.
Within that method, I'd iterate (using reflection) over either:
all accessible (or even all declared) fields
all annotated fields
For the latter variant you'll need to implement your own Annotation to mark the desired properties, or just use the existing "#Transient" annotation to sort out the non-wanted ones. Wait, you'll certainly want the annotation to have RetentionPolicy.RUNTIME:
//...
#Retention( RetentionPolicy.RUNTIME )
public #interface MyAnnotation
//...
But maybe you don't even need to explicitly mark or select properties, particularly if your classes are purely value-holding.
Once you've accessed a given property within the suggested loop, simply make use of String.valueOf (ex- or implicitly) to send the "contents" of that property to a writer, or append to a file directly.
Java serialization generally aims to descend further in object "trees", since any of your properties may be a complex object of its own, requiring more or less sophisticated serialization again.
But I've understood that you rather need a simple, "flat" solution here.
You could use a generic interface for the parser.
public interface ParserInterface<T> {
void setObject(T object);
void read();
void write();
}
public class ClassAParser implements ParserInterface<ClassA> { ... }
As Pitelk mentioned, the map of object and parser seems wrong. Instead you'll want to use a map of class to parser:
parsers.add(ClassA.class, new ClassAParser());
// etc.
Besides: creating instances of all parser implementations in the constructor of DataParser is unnecessary overhead. You could create only the needed instance using an if / else if chain and Object.getClass or instanceof in the constructor or make the map a static member of your class.
writeData then becomes:
void <T> writeData()
{
ParserInterface<T> parser = (ParserInterface<T>) parsers.get(this.object.getClass());
parser.setObject((T) this.object); // <-- same method for all of supported types
parser.write();
}
The compiler will generate a warning about unchecked casts. But if used correctly, i.e. parsers.get(c) returns a compatible parser, it can be ignored or suppressed.
I have a servlet with several methods that get a list of objects from the DAO, turn the list into JSON, and send it back in the response. Every list is made of objects that have a method:
public String getAsJson(){...}
And the servlet has a bunch of mostly identical methods that look like:
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
StringBuilder builder = new StringBuilder();
builder.append('[');
// loops over the list appending the value of each objects getAsJson()
builder.append(']');
return builder.toString();
}
The problem is that I have about 6 methods (and growing) that look exactly like that except for different DAO queries. My idea was to create an interface that only had the definition for the getAsJson() method, make each bean implement that, and then have another method in the servlet that took objects that implemented that interface. Ended up looking like this:
public Interface JsonEnabled {
public String getAsJson();
}
public class User implements JsonEnabled {
....
#Override
public String getAsJson() {...}
}
public class TheServlet {
...
private String getUserListAsJson() {
List<User> userList = this.dao.getUsers();
return this.getListAsJson(userList);
}
private String getListAsJson(List<? implements JsonEnabled> list) {
// The loop code that is in each method.
}
}
That doesn't compile though. After looking up some documentation from Oracle, you can only have extends and not implements for generic parameters. Making all the classes extend from an Abstract Class that just has the getAsJson() method doesn't make sense semantically (the classes are unrelated).
I haven't found a good solution on SO or just googling around, so any help/insight would be appreciated.
For generic wildcards the keyword extends works for both classes and interfaces:
private String getListAsJson(List<? extends JsonEnabled> list) { ... }
extends has slightly different meaning when used for defining generic bounds - it essentially translates to "is, or extends, or implements".
Why don't just use
private String getListAsJson(List<JsonEnabled> list) { ... }
?