How to create a method with an object wildcard (parameter) in Java? - java

Problem<NQueensBoard, QueenAction> problem = new GeneralProblem<>(createBoard(),
TailoredNQF::getIFActions, TailoredNQF::getResult, TailoredNQF::testGoal);
SearchForActions<NQueensBoard, QueenAction> search = new BreadthFirstSearch<>(new GraphSearch<>());
Optional<List<QueenAction>> actions = search.findActions(problem);
actions.ifPresent(qActions -> qActions.forEach(System.out::println));
System.out.println(search.getMetrics());
I want "BreadthFirstSearch" to be some kind of a wildcard(*) (or parameter in a method structure) here, so that I can run this entire piece of code just as;
runCode(BreadthFirstSearch);
runCode(DepthFirstSearch);
...
without repeating.
How can I do it?

You will need to use an interface or an abstract class and dependency injection, to inject the type of object search you want to do. The code will look something like this:
public interface SearchForAction<N, Q> {
Optional<List<Q>> findActions(Problem<N, Q> problem);
}
public class BreadthFirstSearch implements SearchForAction<N, Q> {
Optional<List<Q>> findActions(Problem<N, Q> problem) {
// Do your action
}
}
public class SearchEngine<N, Q> {
private SearchForAction<N, Q> searchForAction;
public Optional<List<Q>> runCode(SearchForAction<N, Q> searchForAction, Problem<N, Q> problem) {
this.searchForAction = searchForAction;
return this.searchForAction.findActions(problem);
}
}
public class Program {
private SearchEngine<NQueensBoard, QueenAction> searchEngine = new SearchEngine<>();
private SearchForActions<NQueensBoard, QueenAction> breadthFirstSearch = new BreadthFirstSearch<>();
private SearchForActions<NQueensBoard, QueenAction> depthFirstSearch = new DepthFirstSearch<>();
// In your program call your method and you inject your dependency
searchEngine.runCode(breadthFirstSearch);
searchEngine.runCode(depthFirstSearch);
}

Related

Pass new object with the use of setter in method parameters

I'm trying to pass new Object as method parameter and set it's variable at the same time.
This an okay solution but big and not nice...
EventBox evtbox = new EventBox();
evtbox.setFloorColor(floorColor);
scriptUtils.runScript("sc-cfrmd",evtbox);
and I need something like this to shorten it up a bit
scriptUtils.runScript("sc-cfrmd",new EventBox().setFloorColor(floorColor));
of course, logical way of doing this is just creating a constructor in EventBox class but I need to figure out way without use of constructors.
any tips are appreciated
You are looking for fluent interface
Usually, when you need to create a complex object you are implementing fluent interface with builder design pattern
For example:
import java.awt.Color;
public class EventBox {
private Color floorColor;
private EventBox() {
this.floorColor = null;
}
public Color getFloorColor() {
return floorColor;
}
private void setFloorColor(Color floorColor) {
this.floorColor = floorColor;
}
public static EventBoxBuilder builder() {
return new EventBoxBuilder();
}
public static class EventBoxBuilder {
private final EventBox box;
EventBoxBuilder() {
this.box = new EventBox();
}
public EventBoxBuilder setFloorColor(Color color) {
box.setFloorColor(color);
return this;
}
public EventBox build() {
return box;
}
}
}
....
scriptUtils.runScript("sc-cfrmd",EventBox.builder().setFloorColor(floorColor).build());
If you are able to use Lombok Framwork, such builder can be automatically generated on compile time by adding #Builder annotation to the EventBox class
You can use method chaining by adding methods as desired. Conventionally, leave the setters/getters as the standard practice to just do what their name says.
public EventBox withFloorColor(String floorColor) {
setFloorColor(floorColor);
return this;
}
scriptUtils.runScript("sc-cfrmd",new EventBox().withFloorColor(floorColor));
The most basic and simple solution is of course to create a method like
EventBox createFloorEventBox( String floorColor ) {
EventBox eb = new EventBox();
eb.setFloorColor( floorColor );
return eb;
}
and use it like
scriptUtils.runScript("sc-cfrmd", createEventBox( floorColor ) );
Besides the builder pattern/method chaining/fluent approach, you could also consider using lambdas in Java, like
void runScript(String something, Consumer<EventBox> boxInitializer) {
EventBox eb = new EventBox();
initializer.apply(eb);
...
}
and then call this like
runScript("something", eb -> eb.setFloorColor( floorColor ));

Java Filter Factory implementation

Inspired by FilenameFilter.java, I want to use similar approach/design pattern to solve my problem. I have select files from sftp server based on:
If it is older than n days
If it is older than n days and its name is in certain pattern.
I have defined a functional interface SemanticFileFilter as below:
public interface SftpFileFilter
{
boolean accept(LsEntry sftpFile);
}
LsEntry for sftp is basically something like File in java.
Wanted to define SftpFileFilterFactory to get all implementation of SftpFileFilter at one place like below:
public class SftpFileFilterFactory
{
public static final SftpFileFilter OLD_FILE_FILTER = new SftpFileFilter()
{
//ERROR: because Interface function method should take only 1 parameter
//#Override
public boolean accept(LsEntry lsEntry,int nDays)
{
//checks if files if older than nDays
}
};
public static final SftpFileFilter PATTERN_MATCH_OLD_FILE_FILTER = new SftpFileFilter()
{
//ERROR: because Interface function method should take only 1 parameter
//#Override
public boolean accept(LsEntry lsEntry,int nDays, String pattern)
{
//checks if files if older than nDays and matches pattern "pattern"
}
};
}
How do I design my interface's function method or factory implementation so that in future if similar more filters needs to be defined, I don't need to bother much in code changes but just define new filter.
Also we should be able to chain filters. That is to say define one filter for older files and another for pattern matching. If both needs to used they should be able to chained together and hence both could be used.
Your problem reminds Command design pattern. You need to implement different conditions and to provide additional parameters you can use constructors and create classes or use Java 8 lambda expressions. See below example:
import java.util.ArrayList;
import java.util.List;
public class DesignPatterns {
public static void main(String[] args) {
List<SftpFileFilter> filters = new ArrayList<>();
filters.add(new OlderThanNDaysFilter(10));
filters.add(new NameSftpFileFilter("tmp.txt"));
// you can use lambda as well
filters.add((file) -> file.getName().length() > 0);
}
}
interface SftpFileFilter {
boolean accept(LsEntry sftpFile);
}
class OlderThanNDaysFilter implements SftpFileFilter {
private final int days;
public OlderThanNDaysFilter(int days) {
this.days = days;
}
#Override
public boolean accept(LsEntry sftpFile) {
return sftpFile.isOlder(days);
}
}
class NameSftpFileFilter implements SftpFileFilter {
private final String name;
public NameSftpFileFilter(String name) {
this.name = name;
}
#Override
public boolean accept(LsEntry sftpFile) {
return sftpFile.getName().equals(name);
}
}
These objects are too small and there is not need to create factory for it. You can create and use them if it is necessary. Of course, you can create factory which creates some predefined filters:
class ConditionFactory {
private static final SftpFileFilter OLDER_THAN_TEN = new OlderThanNDaysFilter(10);
private static final SftpFileFilter PASSWORDS_FILE = new NameSftpFileFilter("passwords.txt");
public SftpFileFilter createOlderThan10Days() {
return OLDER_THAN_TEN;
}
public SftpFileFilter createPasswordsFile() {
return PASSWORDS_FILE;
}
public SftpFileFilter createNameFilter(final String name) {
return new NameSftpFileFilter(Objects.requireNonNull(name));
}
public SftpFileFilter createOlderThan(final int days) {
return new OlderThanNDaysFilter(days);
}
}
It is a good separation between filter implementations and client code which does not know anything how filtering by name is implemented and can be easily exchanged.
In Java 8 you can use java.util.function.Predicate directly or extend it by your interface:
interface SftpFileFilter extends Predicate<LsEntry> {
boolean accept(LsEntry sftpFile);
#Override
default boolean test(LsEntry lsEntry) {
return accept(lsEntry);
}
}

How to avoid a circular reference in Java

I'm trying to create two different classes that represent different options of exercises the user can choose to sort by. After one class is chosen, the other is no longer an option, because of this I create an ArrayList in both classes of classes which are not allowed to follow it.
The problem is that since they are not able to follow each other, when these classes are constructed it results in an infinite loop, is there any way I can avoid this?
PushPullLegs Class
public class PushPullLegs extends SortingGroup implements Serializable{
public PushPullLegs(){
this.setName("Push,Pull,Legs");
this.addCantFollow(new MuscleGroup());
SortingCategory push = new SortingCategory("Push","PPL","Push");
this.addOption(push);
SortingCategory pull = new SortingCategory("Pull","PPL","Pull");
this.addOption(pull);
SortingCategory legs = new SortingCategory("Legs","PPL","Legs");
this.addOption(legs);
}
}
MuscleGroup Class
public class MuscleGroup extends SortingGroup implements Serializable {
public MuscleGroup(){
this.addCantFollow(new PushPullLegs());
SortingCategory chest = new SortingCategory("Chest","Primary","Chest");
chest.addNewOptions(new ChestMovementPatterns());
this.addOption(chest);
SortingCategory triceps = new SortingCategory("Triceps","Primary","Triceps");
triceps.addNewOptions(new TricepMovementPatterns());
this.addOption(triceps);
SortingCategory lats = new SortingCategory("Lats","Primary","Lats");
this.addOption(lats);
SortingCategory quads = new SortingCategory("Quads","Primary","Quads");
this.addOption(quads);
SortingCategory hamstrings = new SortingCategory("Hamstrings","Primary","Hamstrings");
this.addOption(hamstrings);
}
}
You would use code like this:
private Set<Class<? extends SortingGroup>> cantFollowClass = new HashSet<>();
public void addCantFollow(Class<? extends SortingGroup> clazz) {
this.cantFollowClass = clazz;
}
public boolean canFollow(SortingGroup group) {
return ! this.cantFollowClass.contains(group.getClass());
}

Rx-Java: Creating a configurable Observable

I'm new to RxJava, and I am wondering how I can create a configurable Observable? Let's imagine I could write a DB-to-DB transfer like this:
srcDb.getObservable(Bean.class)
.sql(selectSql)
.params(selectParams)
.subscribe(
trgDb.getSubscriber(Bean.class)
.sql(insertSql)
);
I can already do that with the Subscriber, but how can I get some small configuration in the same fashion to the Observable itself?
There's 2 ways you can do that:
Option #1: have your own objects do the configuration, and then have an execute(), query() or toObservable() that switches domains:
srcDb
.find(Bean.class)
.sql(selectSql)
.params(selectParams)
.execute()
.subscribe(
trgDb.getSubscriber(Bean.class)
.sql(insertSql)
);
Option #2: use .compose() to re-use common operations:
srcDb
.getObservable(Bean.class)
.compose(addSQLParameters())
.subscribe(
trgDb.getSubscriber(Bean.class)
.sql(insertSql)
);
<T> Transformer<T,T> addSQLParameters() {
return obs -> obs.sql(selectSql).params(selectParams);
}
I would suggest you use option #1, as it allows much better management of your part of the code.
Maybe I found an acceptable way around this. It seems that what I need to do here is a double-binding outside of the Observable instantiation itself. E.g. I need a DbObservable and DbOnSubscribe pair which is counting on each other, something like this:
DbObservable class:
public class DbObservable<T> extends Observable<T> {
//Some parameter
private String sql;
protected DbObservable(DbOnSubscribe<T> onSub) {
super(onSub);
}
//Getter for DbOnSubscribe
public String getSql() {
return sql;
}
//Chain parameter modifier
public DbObservable<T> sql(String sql) {
this.sql = sql;
return this;
}
}
DbOnSubscribe class:
public class DbOnSubscribe<T> implements Observable.OnSubscribe<T> {
private DbObservable<T> dbObservable;
#Override
public void call(Subscriber<? super T> subscriber) {
String sql = dbObservable.getSql(); //Access SQL param
subscriber.onNext( (T) sql ); //Use subscriber
subscriber.onCompleted();
}
//Set back-reference
public void setDbObservable(DbObservable<T> dbObservable) {
this.dbObservable = dbObservable;
}
}
And finally our assumed DbConnector class:
public class DbConnector {
public DbObservable<String> getObservable() {
DbOnSubscribe<String> onSub = new DbOnSubscribe<String>();
DbObservable<String> obs = new DbObservable<>(onSub);
onSub.setDbObservable(obs);
return obs;
}
}
So when I try it out ...
public class DbObservableTest {
public static void main(String[] args) {
DbConnector srcDb = new DbConnector();
srcDb.getObservable()
.sql("some SQL")
.subscribe(System.out::println);
}
}
... it really works! It prints out the "some SQL".
Conclusion
If you want to be super-clean and don't mind one or 2 extra lines of code, go for a builder as proposed by Joel and Tassos Bassoukos.
If you're not afraid of a little bit more complicated code (which should be always encapsulated somewhere) and you really want those parameters to be inside your own Observable, you can try the double-binding way
Any more options?

Using a fluent builder pattern without inner static classes for workflow

This is a continuation from what I was working in Passing 1 to many parameters of same object type
I've gotten good feedback on that , I believe i have the improved the design . The whole code is at https://github.com/spakai/flow_input_builder
The requirement is simple : -
I need to build a set of input for different workflows using 1 or more outputs from previous workflows
I have a set of interfaces
public interface SwfInput {
}
public interface SwfOutput {
}
public interface Workflow<I extends SwfInput, O extends SwfOutput> {
public O execute(I input);
}
public interface Builder<I extends SwfInput> {
public I build();
}
Now , Say I have 3 flows which gets executed in sequence FlowA->FlowB->FlowC
FlowC needs mandatory output from FlowB but only optionally from FlowA
so I have a implementation for FlowCBuilder
public class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowBOutput mandatoryflowBOutput;
private FlowAOutput optionalflowAOutput;
public FlowAOutput getOptionalflowAOutput() {
return optionalflowAOutput;
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
this.optionalflowAOutput = optionalflowAOutput;
return this;
}
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
this.mandatoryflowBOutput = mandatoryflowBOutput;
}
#Override
public FlowCInput build() {
FlowCInput input = new FlowCInput();
input.setMandatoryFromFlowB(mandatoryflowBOutput.getOutput1FromB());
if (optionalflowAOutput != null) {
input.setOptionalFromFlowA(optionalflowAOutput.getOutput2FromA());
}
return input;
}
}
one test i have written shows an example usage
FlowBOutput mandatoryflowBOutput = new FlowBOutput();
mandatoryflowBOutput.setOutput1FromB("iNeedThis");
FlowAOutput optionalflowAOutput = new FlowAOutput();
FlowCInput input = new FlowCInputBuilder(mandatoryflowBOutput)
.setOptionalflowAOutput(optionalflowAOutput)
.build();
I have not used static inner class for the Builder pattern.
Any suggestions are welcomed.
You should use static inner class. The key point of using this approach is that, the inner can directly access private properties of the object being constructed. This helps eliminating duplicated code since the builder does not need to maintain a long list of temporary state for the constructing. So, your code can be rewritten like this:
public class FlowCInput {
private int output1FromB; // suppose that it is int
private String output2FromA; // suppose that it is String
private FlowCInput() { }
//...
public static class FlowCInputBuilder implements Builder<FlowCInput> {
private final FlowCInput result;
public FlowCInputBuilder(FlowBOutput mandatoryflowBOutput) {
result = new FlowCInput();
// output1FromB is private but still accessed from here
result.output1FromB = mandatoryflowBOutput.getOutput1FromB();
}
public FlowCInputBuilder setOptionalflowAOutput(FlowAOutput optionalflowAOutput) {
// same for output2FromA
result.output2FromA = optionalflowAOutput.getOutput2FromA();
return this;
}
#Override
public FlowCInput build() {
return result;
}
}
}
As you see, the builder now holds only a FlowCInput object, it does not unnecessarily hold mandatoryflowBOutput and optionalflowAOutput as before.

Categories