What design pattern to avoid overloading functions - java

I am currently writing a program that turns a String into an int
I got my own rules example : ("37dsqff" = 37) ("50 km/h" = 50)
The problem is the String can be any kind (StringBuffer, Vector, InputStream...) and i don't have any control on it.
So far I have made 1 parseInt() function for each one.
It looks this way :
public class Tools {
public static int parseInt(StringBuffer s)
{
...
return n;
}
public static int parseInt(Vector<Character> v)
{
...
return n;
}
....
}
I have noticed that every functions share too much similarities and I would like to use a design pattern to make it better and only have 1 parseInt function
I think about Visitor, template method but i don't know what s the best here.

The easiest (and generally simplest) technique is to find common interfaces and see if you can implement your function at that more general level.
Something like:
public static class Tools {
// CharSequence covers both String and StringBuilder.
public static int parseInt(CharSequence s) {
return 4;
}
// Use Iterable instead of Vector (Vector implements List).
public static int parseInt(Iterable<Character> v) {
return 6;
}
}
Once complete you can take it a little further by writing adaptors that transform one structure into another. This will make an Iterable<Character> out of a CharSequence.
// Make an Iterable<Character> from a CharSequence.
public static class CharWalker implements Iterable<Character> {
final CharSequence s;
public CharWalker(CharSequence s) {
this.s = s;
}
#Override
public Iterator<Character> iterator() {
return new Iterator<Character>() {
int i = 0;
#Override
public boolean hasNext() {
return i < s.length();
}
#Override
public Character next() {
return s.charAt(i++);
}
};
}
}
So now we can fold the two together into one:
public static class Tools {
// CharSequence covers both String and StringBuilder.
public static int parseInt(CharSequence s) {
// Forward to the Iterable version below.
return parseInt(new CharWalker(s));
}
// Use Iterable instead of Vector (Vector implements List).
public static int parseInt(Iterable<Character> v) {
return 6;
}
}

Related

Question on diamond operator for design pattern strategy

Small question regarding the diamond operator and design pattern strategy for Java, please.
I would like to implement a very specific requirement:
there are some objects to store (in my example called MyThingToStore)
and the requirement is to store them with different kinds of data structures, for comparison.
Therefore, I went to try with a strategy pattern, where each of the strategies is a different way to store, I think this pattern is quite lovely.
The code is as follows:
public class MyThingToStore {
private final String name;
public MyThingToStore(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyThingToStore that = (MyThingToStore) o;
return Objects.equals(name, that.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "MyThingToStore{" +
"name='" + name + '\'' +
'}';
}
}
public class MyStorage {
private final StorageStrategy storageStrategy;
public MyStorage(StorageStrategy storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
public interface StorageStrategy {
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy{
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And this is working fine, very happy, especially tackled the requirement "easy to change the data structure to do the actual store".
(By the way, side question, if there is an even better way to do this, please let me know!)
Now, looking online at different implementations of strategy patterns, I see this diamond operator which I am having a hard time understanding:
MyThingToStore stays the same.
public class MyStorage {
private final StorageStrategy<MyThingToStore> storageStrategy; //note the diamond here
public MyStorage(StorageStrategy<MyThingToStore> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
#Override
public String toString() {
return "MyStorage{" +
"storageStrategy=" + storageStrategy +
'}';
}
}
public interface StorageStrategy<MyThingToStore> {
//note the diamond, and it will be colored differently in IDEs
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy<MyThingToStore> {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy<MyThingToStore> {
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy<MyThingToStore> storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And both versions will yield the same good result, also be able to answer requirements.
My question is: what are the differences between the version without a diamond operator, and the version with the diamond operator, please?
Which of the two ways are "better" and why?
While this question might appear to be "too vague", I believe there is a reason for a better choice.
I think the confusion comes from how you named type parameter for StorageStrategy in your 2nd example.
Let's name it T for type instead. T in this case is just a placeholder to express what type of objects your StorageStrategy can work with.
public interface StorageStrategy<T> {
void addToStore(T myThingToStore);
int getSize();
}
E.g.
StorageStrategy<MyThingToStore> strategy1 = // Initialization
StorageStrategy<String> strategy2 = // Initialization
strategy1.addToStore(new MyThingToStore("Apple"));
// This works fine, because strategy2 accepts "String" instead of "MyThingToStore"
strategy2.addToStore("Apple");
// Last line doesn't work, because strategy1 can only handle objects of type "MyThingToStore"
strategy1.addToStore("Apple");
To make it work properly, you need to change your different StorageStrategy implementations to also include the type parameter.
public class StorageUsingHashSetStrategy<T> implements StorageStrategy<T> {
private final Set<T> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(T myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
And lastly you also want to have a type paremeter for MyStorage
public class MyStorage<T> {
private final StorageStrategy<T> storageStrategy;
public MyStorage(StorageStrategy<T> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(T myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
Now you can create a MyStorage and can use it to store essentially any object into it and not just MyThingToStore. Whether that is something you want or not is up to you.
In the second code sample in the declaration of the interface StorageStrategy<MyThingToStore>, MyThingToStore is a Type Variable.
I.e. it's not the actual type, only a placeholder for a type, like T. The common convention is to use single-letter generic type variables (T, U, R, etc.), otherwise it might look confusing like in this case.
Note that in the class declarations, like:
public class StorageUsingArrayListStrategy
implements StorageStrategy<MyThingToStore>
MyThingToStore is no longer a type variable, but the name of the class MyThingToStore because in this case parameterized interface is implemented by a non-parameterized class (i.e. the actual type known to the compile is expected to be provided).

Implementing a functional interface via method reference

First I got a class named after my Chinese name
public class Yxj<T> {
private T[] data;
private int size = 0;
private final Comparator<? super T> comparator;
public Yxj(Comparator<? super T> c) {
data= (T[]) new Object[16];
comparator = c;
}
public void addItem(T t){
data[size++] = t;
}
public int sort(){
return comparator.compare(data[0], data[1]);
}
public T[] getData(){
return data;
}
}
in which a Comparator resides,then I defined a Norwich keeping a field order and setter and getter of it, finally there's a method used to implement the compare(T t1,T t2) in Comparator.
public class Norwich {
private int order;
public Norwich(int o) {
order = o;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public int compareOrder(Norwich n) {
if (order > n.getOrder()) {
return 2;
} else if (order == n.getOrder()) {
return 0;
} else {
return -3;
}
}
}
then here comes the main method
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
System.out.println(norwichYxj.sort());
so what I'm interested in is that, why does not the method compareOrder keep the same parameters as the compare in Comparator but it can still work correctly?
It is simple. You have passed through the constructor your implementation of the Comparator to be used for comparing.
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Remember Comparator is nothing else than an interface. Since it is a functional interface, it can be represented through a lambda expression or a
method reference (as you did). The way you can pass the Comparator in the full form is as follows. Note the usage of the compareOrder method:
Yxj<Norwich> norwichYxj = new Yxj<>(new Comparator<>() {
#Override
public int compare(Norwich o1, Norwich o2) {
return o1.compareOrder(o2); // usage of compareOrder
}
});
This can be shortened to a lambda expression:
Yxj<Norwich> norwichYxj = new Yxj<>((o1, o2) -> o1.compareOrder(o2));
It can be shortened again to a method reference:
Yxj<Norwich> norwichYxj = new Yxj<>(Norwich::compareOrder);
Now you can see it can be represented in this way though the method compareOrder accepts only one formal parameter. The first parameter of the Comparator#compare method is the one invoking the compareOrder method and the second parameter is the one being passed to the compareOrder method.
Learn more here: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Additionally, the classes you have constructed look a bit odd. Though the other answer doesn't in fact answer your question, it can lead you to a better code: Implementing a functional interface via method reference
class Yxj
The paramter T of your class Yxj should have more restrictions if you want to compare/sort in this class with T then say T must be comparable.
If your T array grows then don't implement your own growing array but use ArrayList instead which does that for you
If you do the first you don't need the Comperator anymore
Your methode sort only sorts the first and second element so you will get problems. If the data is shorter you will get an ArrayIndexOutOfBoundsException if it is longer it won't sort the rest of elements. So with a Collection you could simple use Collections.sort(data);
public class Yxj<T extends Comparable<T>> {
private final List<T> data;
public Yxj() {
this.data = new ArrayList<>();
}
public void addItem(T t){
data.add(t);
}
public void sort(){
Collections.sort(data);
}
public List<T> getData(){
return data;
}
public void print(){
System.out.println(data);
}
}
class Norwich
If you done the above know your Norwich class must implement the Comparable interface so you can compare Norwich instances with the methode compareTo which also will be called each time you or the API ask directly or indirectly to compare to Norwich instances like for sorting ect.
public class Norwich implements Comparable<Norwich> {
private int order;
public Norwich(int o) {
this.order = o;
}
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
#Override
public int compareTo(Norwich other) {
return this.order - other.order;
}
#Override
public String toString() {
return "Norwich{" +
"order=" + order +
'}';
}
}
Main
Done? Perfect, then your main could be looks like this
public static void main(String[] args) {
Yxj<Norwich> norwichYxj = new Yxj<>();
norwichYxj.addItem(new Norwich(9));
norwichYxj.addItem(new Norwich(1));
norwichYxj.sort();
norwichYxj.print();
}

Is there a different way to write get methods in Java?

I know that we can retrieve a variable's value by simply writing get methods and return var;. However, is there another way to write a get method to return information on the fields instead? If so, how does one access it. For example, if I have a planeNumber and I want to check it against another object's planeNumber, is there a way to use a boolean to check instead of writing public int getPlaneNumber()?
Seems like you are wanting to implement the Comparable interface? https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
That is it looks like you have an attribute, planeNumber, that you want to use to compare the classes?
Maybe you want something like this
import java.util.Comparator;
import java.util.Objects;
public class Airplane implements Comparable<Airplane> {
private final int planeNumber;
public Airplane(final int planeNumber) {
this.planeNumber = planeNumber;
}
public final int getPlaneNumber() {
return planeNumber;
}
#Override
public int compareTo(final Airplane o) {
return Objects.compare(this, o, Comparator.comparing(Airplane::getPlaneNumber));
}
public static void main(final String... args) {
System.out.println(new Airplane(1).compareTo(new Airplane(2)));
System.out.println(new Airplane(100).compareTo(new Airplane(100)));
System.out.println(new Airplane(1000).compareTo(new Airplane(100)));
}
}
-1
0
1
You could add a method comparing the field values to your class like this (omitting null check in the methods):
class Scratch {
public static void main(String[] args) {
ObjectWithPlaneNumber o1 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o2 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o3 = new ObjectWithPlaneNumber(11);
System.out.println(o1.hasSamePlaneNumber(o2));
System.out.println(o1.hasSamePlaneNumber(o3));
}
static class ObjectWithPlaneNumber {
private final int planeNumber;
public ObjectWithPlaneNumber(int planeNumber) {
this.planeNumber = planeNumber;
}
public boolean hasSamePlaneNumber(ObjectWithPlaneNumber other) {
return this.planeNumber == other.planeNumber;
}
}
}

JNA callback function with pointer to structure argument

I am busy with a project in which I have to do native calls to a proprietary C library. I came across JNA, which seems to be tried and tested with a number of successful projects.
I am having trouble passing a structure (or pointer to) through to a callback function. I have tried many different scenarios before, and basically, any structure member that requires memory allocation, like a String (char *), for instance, is null when I retrieve it.
I have tried to illustrate the problem with the following example:
C code:
typedef struct {
int number;
char *string;
} TEST_STRUCT;
typedef union {
int number;
TEST_STRUCT test_struct;
} TEST_UNION;
typedef void (*TEST_CB)(TEST_UNION*);
void test(TEST_CB test_cb)
{
TEST_STRUCT *test_struct = malloc(sizeof *test_struct);
test_struct->number = 5;
test_struct->string = "Hello";
TEST_UNION *test_union = malloc(sizeof *test_union);
test_union->number = 10;
test_union->test_struct = *test_struct;
test_cb(test_union);
free(test_struct);
free(test_union);
}
Java-code:
public interface TestLib extends Library
{
class TestStruct extends Structure
{
public int number;
public String string;
public TestStruct() {
super();
}
protected List<? > getFieldOrder() {
return Arrays.asList("number", "string");
}
public TestStruct(int number, String string) {
super();
this.number = number;
this.string = string;
}
public TestStruct(Pointer peer) {
super(peer);
}
public static class ByReference extends MBTStatus implements Structure.ByReference {}
public static class ByValue extends MBTStatus implements Structure.ByValue {}
}
class TestUnion extends Union {
public int number;
public TestStruct testStruct;
public TestUnion() {
super();
}
public TestUnion(int number, TestStruct testStruct) {
super();
this.number = number;
this.testStruct = testStruct;
}
public TestUnion(Pointer pointer) {
super(pointer);
}
public static class ByReference extends TestUnion implements com.sun.jna.Structure.ByReference {}
public static class ByValue extends TestUnion implements com.sun.jna.Structure.ByValue {}
}
interface TestCallback extends Callback
{
public void callback(TestUnion testUnion);
}
void test(TestCallback testCallback);
}
The main Java class:
public class TestMain
{
static
{
System.loadLibrary("test");
}
public static void main (String [] args)
{
TestLib.INSTANCE.test(
new TestLib.TestCallback()
{
public void callback(TestLib.TestUnion testUnion)
{
System.out.println(testUnion.testStruct.string == null ? "The string value is null" : "The string value is: " + testUnion.testStruct.string);
}
}
);
}
}
The string value is then null:
The string value is null
I am a complete noob when it comes to JNA, so I have lots to learn. I'm not sure if the mapping of the structure is correct, which might be the cause of the null value.
Any help will be greatly appreciated!
EDIT: I made the question a bit more interesting:
So the argument to a callback function is a union, instead of a struct. The struct is now part of the union. When I do it this way, the value of the struct string variable seems to be null as well.
I just found the answer to the updated question myself. This example ultimatley shows how to do it. As a union only takes up the memory of its largest member, its type has to be set to that member. The Union.read() function must then be called to read the "selected" variable. This is done as follows:
testUnion.setType(TestLib.TestStruct.class);
testUnion.read();
The testStruct variable can then be accessed. The correct callback function is then:
public void callback(TestLib.TestUnion testUnion)
{
testUnion.setType(TestLib.TestStruct.class);
testUnion.read();
System.out.println(testUnion.testStruct.string == null ? "The string value is null" : "The string value is: " + testUnion.testStruct.string);
}
It might be useful when you implement the Union's Pointer-based constructor to invoke read after calling super, and override read() so that it always does the right thing, e.g.
class MyStructure1 {
public int type;
public int intField;
}
class MyStructure2 {
public int type;
public float floatField;
}
class MyUnion extends Union {
public int type;
public MyStructure1 s1;
public MyStructure2 s2;
public MyUnion(Pointer p) {
super(p);
read();
}
protected void read() {
int type = getPointer().getInt(0);
switch(type) {
case 0: setType(MyStruct1); break;
case 1: setType(MyStruct2); break;
}
super.read();
}
}
JNA will generally try to auto-populate as much data as it can if the union's type has not been set, avoiding any pointer fields (like strings) which might result in memory faults if they contain invalid data.

Array of methods: Adapter Pattern?

Problem Description:
I want to be able to pass around a list of methods to other classes where the methods have been defined in only one class. If the methods, some of which have input parameters and non-void return types, are defined in one class, I want to be able to pass a list of some of them, with possible duplicates, as a parameter to some other class's constructor.
Code Description:
The code below is a crude example and can be ignored if it detracts from the main goal. Another example, in addition to the one below, would be a case where the methods are int Add(int n1, int n2), int Subtract(int n1, int n2), Multiply, etc.. and the interface has a method called int MathOperation(int n1, int n2).
Attempt to solve the problem:
The adapter pattern seems to have the functionality I'm looking for but I have only seen examples where the methods in the interface have no input or output parameters. An example implementation I wrote just for this question is posted below.
Problem Analogy:
You have a random picture generator web service. There are 30 mutations that can be applied to an image. The client connects and clicks a "generate" button and a random list of some of those functions are passed to some other class within the web service which then proceeds to run those functions with it's own data while also collecting and possibly re-using the return values to generate some mutated cat image. It can't just explicitly call the methods in the other class because that process needs to be done randomly at run-time. That is why I lean towards the idea of generating a random list of methods which are executed in-order when the 'generate' button is clicked.
I hope I have been clear.
public class SomeClass {
...
public double UseWrench(double torque, boolean clockwise) { ... }
public double UsePliers(double torque, boolean clockwise) { ... }
public double UseScrewDriver(double torque, boolean clockwise) { ... }
public boolean UseWireCutters(double torque) { ... }
interface IToolActions {
double TurnFastener(double torque, boolean clockwise);
boolean CutWire(double torque);
}
private IToolActions[] toolActions = new IToolActions[] {
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UseWrench(double torque, boolean clockwise); } },
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UsePliers(double torque, boolean clockwise); } },
new IToolActions() { public double TurnFastener(double torque, boolean clockwise) { double UseScrewDriver(double torque, boolean clockwise); } },
new IToolActions() { public boolean CutWire(double torque) { boolean UseWireCutters(double torque); } },
};
}
public class Worker<T> {
public List<? extends IToolActions> toolActions;
public Worker(List<? extends IToolActions> initialToolSet){
toolActions = initialToolActions;
}
}
While #alainlompo has the general idea, Java 8 simplifies this greatly by using something such as BiConsumer (for doubles) or even just a Consumer for the class object. In fact, you can go really crazy, and have a method accept varargs lambdas:
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
}
public class Worker {
#SafeVarargs
public Worker(SomeClass example, Consumer<? extends SomeClass>... operations) {
for (Consumer bc : operations) {
bc.accept(example);
}
}
}
Then, this is easily simplified:
SomeClass c = new SomeClass();
new Worker(c, SomeClass::useWrench, SomeClass:usePliers, SomeClass::useScrewDriver, SomeClass::useWireCutters);
While it seems a little awkward applying it like that (due to it being an Adapter pattern), you can easily see how this could apply to a class body:
public class SomeClass
public double useWrench(double torque, boolean clockwise) { ... }
public double usePliers(double torque, boolean clockwise) { ... }
public double useScrewDriver(double torque, boolean clockwise) { ... }
public boolean useWireCutters(double torque) { ... }
#SafeVarargs
public void operate(Consumer<? extends SomeClass>... operations) {
for (Consumer<? extends SomeClass> bc : operations) {
bc.accept(example);
}
}
}
//Elsewheres
SomeClass c = new SomeClass();
c.operate(SomeClass::useWrench, SomeClass:usePliers, SomeClass::useScrewDriver, SomeClass::useWireCutters);
Of course, you don't need varargs, it will work just as well simply passing a Collection
But wait there's more!!!
If you wanted a result, you can even use a self-returning method via a Function, e.g.:
public class SomeClass {
public double chanceOfSuccess(Function<? super SomeClass, ? extends Double> modifier) {
double back = /* some pre-determined result */;
return modifier.apply(back); //apply our external modifier
}
}
//With our old 'c'
double odds = c.chanceOfSuccess(d -> d * 2); //twice as likely!
There's so much more flexibility provided from the Function API in java 8, making complex problems like this incredibly simplified to write.
#John here is how I have approached a solution to your problem.
I used the case of MathOperations to make it simpler. I think first that I would be better to have the interface outside of SomeClass like:
public interface MathOperable {
public int mathOperation(int n1, int n2);
}
I created two examples of classes implementing this interface and one anonymous implementation inside SomeClass (I did an Add, Multiply and an anonymous "Substract")
public class Add implements MathOperable {
public int mathOperation(int n1, int n2) {
return n1 + n2;
}
public String toString() {
return "<addition>";
}
}
The overriding of toString() is simply for the purpose of giving more readability to the examples that I will show at the end of my post.
public class Multiply implements MathOperable {
public int mathOperation(int n1, int n2) {
// TODO Auto-generated method stub
return n1 * n2;
}
public String toString() {
return "<multiplication>";
}
}
Here is my SomeClass class, it contans a getRandomListOfOperations, where I simulate what happens when the click on the button is done
public class SomeClass {
private static MathOperable addition = new Add();
private static MathOperable multiplication = new Multiply();
// Anonymous substraction
private static MathOperable substraction = new MathOperable() {
public int mathOperation(int n1, int n2) {
// TODO Auto-generated method stub
return n1-n2;
}
public String toString() {
return "<substraction>";
}
};
public List<MathOperable> getRandomListOfOperations() {
// We put the methods in an array so that we can pick them up later randomly
MathOperable[] methods = new MathOperable[] {addition, multiplication, substraction};
Random r = new Random();
// Since duplication is possible whe randomly generate the number of methods to send
// among three so if numberOfMethods > 3 we are sure there will be duplicates
int numberOfMethods = r.nextInt(10);
List<MathOperable> methodsList = new ArrayList<MathOperable>();
// We pick randomly the methods with duplicates
for (int i = 0; i < numberOfMethods; i++) {
methodsList.add(methods[r.nextInt(3)]);
}
return methodsList;
}
public void contactSomeOtherClass() {
new SomeOtherClass(getRandomListOfOperations());
}
}
Now here is my SomeOtherClass (which may correspond to your Worker class)
public class SomeOtherClass<T extends MathOperable> {
Random r = new Random();
List<T> operations;
public SomeOtherClass(List<T> operations) {
this.operations = operations;
runIt();
}
public void runIt() {
if (null == operations) {
return;
}
// Let's imagine for example that the new result is taken as operand1 for the next operation
int result = 0;
// Here are examples of the web service own datas
int n10 = r.nextInt(100);
int n20 = r.nextInt(100);
for (int i = 0; i < operations.size(); i++) {
if (i == 0) {
result = operations.get(i).mathOperation(n10, n20);
System.out.println("Result for operation N " + i + " = " + result);
} else {
// Now let's imagine another data from the web service operated with the previous result
int n2 = r.nextInt(100);
result = operations.get(i).mathOperation(result, n2);
System.out.println("Current result for operation N " + i + " which is " + operations.get(i) +" = " + result);
}
}
}
}
I have a simple test class that contains a main to connect the two classes
public class SomeTestClass {
public static void main(String[] args) {
SomeClass classe = new SomeClass();
classe.contactSomeOtherClass();
}
}
Now a few examples of executions:
And another illustration!
I hope this could be helpful!
Okay, I'm going to be "that guy"... the one who understands the question but asks anyway to restate the problem because I think you are on the wrong path. So, bear with me: if you like what you see, great; if not, I understand.
Basically, you have a different intent/motivation/purpose than what "adapter" is suited for. The command pattern is a better fit.
But first, more generally, one of the goals of designing "elements of reusable software" (from the title of the original GOF design patterns book) is that you don't want to modify code when you add functionality; rather, you want to add code without touching existing functionality. So, when you have:
public class Toolbox {
public void hammer() { ... }
}
and you want to add a screwdriver to your toolbox, this is bad:
public class Toolbox {
public void hammer() { ... }
public void screwdriver() { ... }
}
Rather, ideally, all existing code would remain unchanged and you would just add a new Screwdriver compilation unit (i.e., add a new file), and a unit test, and then test the existing code for regression (which should be unlikely, since none of the existing code changed). For example:
public class Toolbox {
public void useTool(Tool t) { t.execute(); ...etc... }
}
public interface Tool { // this is the Command interface
public void execute() // no args (see ctors)
}
public Hammer implements Tool {
public Hammer(Nail nail, Thing t) // args!
public void execute() { nail.into(t); ... }
}
public Screwdriver implements Tool {
public Screwdriver(Screw s, Thing t)
public void execute() { screw.into(t); ... }
}
Hopefully it should become clear how to extend this to your example. The Worker becomes straight-foward list of Tools (or, for clarity, instead of "Tool" , just call it a "Command").
public class Worker {
public List<Command> actionList;
....
public void work() {
for(...) {
action.execute();
}
}
}
This pattern also allows for easy "undo" functionality and "retry", as well as memoization (caching results so they don't have to be re-run).

Categories

Resources