Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)
Related
We have a Java class, WebCenterGrid. This class is full of methods to do things in a grid such as finding a row, finding a cell value, sorting a column. We have several classes that use this class. The classes using it all refer to different grids, but the functionality is the same.
The only thing that differs is how to create the grid. Some classes do a search which populates the grid (search also refreshes). Some do an updateList() to update the grid, etc.
I would like to add a method to WebCenterGrid to refresh the grid. The problem is as I said each method has a different name.
I somehow want to pass into WebCenterGrid the name of a method to call to do the refresh. I have done some searches and found something about lambda which I did not really understand.
I haven't used C++ in a while but there was some way to pass a method into those methods. This class is in Java not C++, but is there some sort of understandable equivalent?
public class WebCenterGrid {
....
....
public void refresh(Method meth) {
meth();
}
}
Basically, there are two ways.
One is to use reflection, this means: relying on runtime type information, commonly derived from raw strings. Like saying: I have some object of class X, and I want to invoke the method named "doTheFoo()" on that object.
See here for all the glory details.
A slightly better way is to use the MethodHandle class, instead of the "raw" reflection Method class. See here for handles.
But then: reflection is happening at runtime. Your code compiles fine, but if you get any detail wrong, it blows up at runtime.
Thus I suggest looking into lambdas, based on Function, see here.
Instead of having a Method parameter, accept an Interface, and the implementation will define what will be called.
You can use lambdas here as well if you'll define your interface as Functional Interface.
Example:
public class Main {
public static void main(String[] args) {
act(new Run());
act(new Swim());
// Passing a body of the function you want to execute
act(() -> System.out.println("walking"));
}
public static void act(Action action) {
action.act();
}
}
#FunctionalInterface
interface Action {
void act();
}
class Run implements Action {
#Override
public void act() {
System.out.println("running");
}
}
class Swim implements Action {
#Override
public void act() {
System.out.println("swimming");
}
}
Output:
running
swimming
walking
If you have predefined refresh logic, you can create association resolver based on mapping which will help you to define proper service based on some conditions.
public class Main {
static Map<ActionType, Action> actionResolver = new HashMap<>();
// Static init is just for brevity sake
static {
actionResolver.put(ActionType.RUN, new Run());
actionResolver.put(ActionType.WALK, new Walk());
actionResolver.put(ActionType.SWIM, new Swim());
}
public static void main(String[] args) {
act(ActionType.RUN);
act(ActionType.WALK);
act(ActionType.SWIM);
}
public static void act(ActionType actionType) {
Action action = actionResolver.get(actionType);
if (action == null)
throw new IllegalArgumentException("ActionType was not registered");
action.act();
}
}
enum ActionType {
RUN,
SWIM,
WALK
}
Output is the same as above.
Well, since we can't see any of your code, I'll suggest the following solution, that's based on my personal assumption about how your code works.
Please keep in mind that this method is not so scale-able and pretty inefficient if you have 100 different ways of creating grids.
However, if you have (e.g. 3) types of such ways for example, you can use constants!
See below:
public class WebCenterGrid {
//Declare constants with meaningful names for grid creation (add more as you like)
public static final int DEEP_COPY=1, SEARCH=2, REBUILD=3;
public void makeDeepCopy(){
//implementation goes here..
}
public void searchAndPopulate(){
//implementation goes here..
}
public void rebuildGrid(){
//implementation goes here..
}
public void refresh(int operation) {
switch(operation) {
//based on 'operation', call appropriate method!
case DEEP_COPY: this.makeDeepCopy(); break;
case SEARCH: this.searchAndPopulate(); break;
case REBUILD: this.rebuildGrid(); break;
//you can have a default operation for any parameter that is not
//in the list of our defined constants(i.e. the number 143)
default: simpleRefresh(); break;
}
}
}
So what makes the above solution work?
Basically, when you call refresh(int operation) from one of your other classes, you need to pass an int as a parameter. That integer is one of the constants defined at the very top of the class. According to which constant was passed, the switch case will determine which method to call.
EXAMPLE (Let's say that AwesomeGridCreator is a class that when it calls refresh(), in order to update a grid, it has to do a search and then populate the grid (like you mention in your question).
We name an integer (for simplicity) SEARCH_POPULATE and we give it ANY value we want. For example 286.
We can then use that constant from any other class, because we don't care what its value is (in this case 286, but the functionality it provides when calling refresh().
public class WebCenterGrid {
/*some code here*/
public static final int SEARCH_POPULATE = 286; //integer value doesn't matter
public void refresh(int operation) {
switch(operation) {
case SEARCH_POPULATE: this.searchAndPopulate(); break;
}
/*...some other code here, we don't care..*/
}
Then, at the 'calling' class:
public class AwesomeGridCreator{
//some code here
WebCenterGrid wcg = new WebCenterGrid();
//The parameter that we pass below (2), will make the refresh() method call
//the method that we defined in our switch cases ('searchAndPopulate()').
wcg.refresh(wcg.SEARCH_POPULATE);
}
I am currently working on a piece of code, in which behavioral decisions are made based on whether the request object is of a certain sub-type, like so:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
...
}
void method(Request request){
if(request instanceof SpecialRequest){
System.out.println("is special...");
}
request.doThing();
}
SpecialRequest in this case has nothing else implemented, that would distinguish it from a normal Request. My question now is, if there are any advantages or disadvantages from using this style instead:
class Request{
...
public boolean isSpecial(){
return special;
}
public void doThing(){
System.out.println("doing Thing...");
}
}
void method(Request request){
if(request.isSpecial()){
System.out.println("is special...");
}
request.doThing();
}
I understand how the second Method could get very convoluted the more decisions I want to make. But I am also interested in how these two approaches compare performance wise.
Thanks in advance.
EDIT: First of all thanks for the quick response. I should have probably mentioned, that my Request and my SpecialRequest are supposed to merely carrying data, and not contain any logic. That's just how the whole software is designed. My method just consumed the request and is supposed to behave differently based on whether the request is special or not. "instanceof" just seems like dirty code to me, but the boolean also doesn't seem quite right. Any advice is still welcome.
The clear advantage of using a method is that it's not closely tied to a particular type. You could add a new class VerySpecialRequest which also provides this behaviour, and you wouldn't necessarily need to extend SpecialRequest in order to do that.
However, the more pressing issue here is that you have explicit conditional branching at all. The object should be responsible for determining whether there's any additional behaviour required, and then the nasty conditional logic goes away altogether:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
#Override
public void doThing(){
super.doThing();
System.out.println("is special...");
}
}
You might also consider using the visitor pattern (https://en.wikipedia.org/wiki/Visitor_pattern), as it ensures type-safety and does not need the instanceof-check. Furthermore it is more obvious where you have to extend/ modify your code, when you create a new type of request (e.g. "VerySpecialRequest").
All you have to do is to create an interface with visit-methods for every type you want to execute special code, like this:
public interface RequestProcessor {
void visit(Request request);
void visit(SpecialRequest specialRequest);
}
The request classes need accept-methods that do nothing but calling the visitor with itself:
public class Request {
...
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Same for SpecialRequest:
public class SpecialRequest extends Request {
...
#Override
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Then you can simply implement your logic in a class that implements the interface (here as an anonymous class):
RequestProcessor requestProcessor = new RequestProcessor() {
#Override
public void visit(Request request) {
System.out.println("I'm a normal request");
}
#Override
public void visit(SpecialRequest specialRequest) {
System.out.println("I'm a special request");
}
};
Request request = new Request();
request.accept(requestProcessor);
SpecialRequest specialRequest = new SpecialRequest();
specialRequest.accept(requestProcessor);
As you can see there are no more instance-of checks. Another advantage of this is that you can "process requests" even if they are no direct subclass of 'Request' - all you have to do is to extract the accept-method in its own interface. Hope this helps.
1.- insteadof, is a type comparison operator because it compares the instance with type. It returns either true or false. If you apply the instanceof operator with any variable that has null value, it returns false.
2.- isSpecial(), is a method of your own. You can do what ever you want in that piece of code, so the comparisson in that case is up to you.
3.- You have to be aware that when you use instanceof, the comparison also do a class cast of the variable in mention, so if that can't be done, you should get a compile time error. see this : compile time error with instanceof
4.- if you use this operator to much, you should check it, because that's a signal of some bad code. For more details see this: use of instaceof
Ok, while I tried to find a title that explains the problem I probably have to expand on it.
Recently I implemented a small program that will be used to control a tape library. Knowing it had to work with multiple different types of tape library so the following design was developed.
interface Tapelibrary<T extends TapeDrive> {
List<T> getListofDrives();
void doSomethingWithDrive(T d);
}
class SpecificTapeLibrary implements Tapelibrary<HPDrive> {
private List<HPDrive> driveList;
SpecificTapeLibrary() {
driveList.add(new HPDrive());
driveList.add(new HPDrive());
driveList.add(new HPDrive());
}
#Override
public List<HPDrive> getListofDrives() {
return driveList;
}
#Override
public void doSomethingWithDrive(HPDrive d) {
d.doSomethingHPspecific();
}
}
abstract class TapeDrive {
void doSomething() {
}
}
class HPDrive extends TapeDrive {
void doSomethingHPspecific() {
}
}
The correct tape library is determined by a factory based on command line arguments.
public static void main(String[] args) {
Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
List<? extends TapeDrive> listOfDrives = t.getListofDrives();
// the user selects a drive by using a small UI or something
TapeDrive selectedDrive = listOfDrives.get(0);
t.doSomethingWithDrive(selectedDrive); // compiler error
}
This does make sense since the compiler would have to explicitly cast the supertype TapeDrive to the subtype HPDrive which is expected by the doSomethingWithDrive(HPDrive) methods in SpecificTapeLibrary
How would this be solved in a good oop way? I ended up not using generics and casting inside the doSomethingWithDrive method (as suggested here:How to Pass a Child Class into a method requiring Super Class as parameter). But that can't be the optimal solution.
While writing this post another solution popped into my head which is much cleaner. The DriveSelector class encapsulates the selection process.
class DriveSelector {
<T> T selectDrive(List<T> inputList) {
// give the user an UI or something to select a drive
return inputList.get(0);
}
}
// the tape library then uses the selector
public void doSomethingWithSelectedDrive(DriveSelector selector) {
HPDrive t = selector.selectDrive(driveList);
t.doSomethingHPspecific();
}
Any other ideas?
Do all of your work in a generic method:
static <T extends TapeDrive> void doStuff(Tapelibrary<T> t) {
List<T> listOfDrives = t.getListofDrives();
// the user selects a drive by using a small UI or something
T selectedDrive = listOfDrives.get(0);
t.doSomethingWithDrive(selectedDrive);
}
Then call this from your main method:
Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
doStuff(t);
Ideone demo
The way this works is that it removes all of the wildcards - the thing about wildcards is that the compiler treats every one as different, even if the values are derived from a single generic instance. By putting things into the generic method like this, you allow the compiler to know that all of the Ts are the same type - thus it can know that the calls are safe.
I have a class collection<T> extends ArrayList()
the object lesCommandes is a collection of multiple Commandes
I stock 3 objects from the class Commandes in it and when i want to apply methods to one of them this.lesCommandes.get(1).xmlCommande() i need to cast it or it doesn't work ((Commande)this.lesCommandes.get(1)).xmlCommande()
class Collection<T> extends ArrayList{}
this.commande1=new Commande(1,10,"filet 1kg",1,"10-12-2015","10-01-2016","en cours");
this.commande2=new Commande(2,15,"filet 5kg",1,"11-11-2015","10-02-2016","livrée");
this.commande3=new Commande(3,20,"caisse 10kg",2,"12-10-2015","10-03-2016","livrée");
this.lesCommandes.add(0, commande1);
this.lesCommandes.add(1, commande2);
this.lesCommandes.add(2, commande3);
xml=((Commande)this.lesCommandes.get(1)).xmlCommande();
You have to extend ArrayList<Commande>, so the objects stored in it will remain of Commande type
First a few advices on design (if I may).
Don't use inheritance for composition.
extends means is a relationship, which is often abused: you can say a GroupOfOrders is a ListOfOrders and define the following (in this case it really means is implemented in terms of):
public GroupOfOrders extends List<Order> {...}
But, it is generally better to define this relation in terms of composition and use the List<T> for the (hidden) implementation.
Why? - because,
you may want to have a hierarchy of GroupOfOrders and you can only extends once,
when you extends you inherit all the public and protected members from the super class. in your case, these methods are not part of the (functional) domain. You may not really want to allow clients of your class to apply any methods from List<T>.
If you decide to change the implementation and say that a GroupOfOrders is actually better implemented with a Set<T>, meaning you don't authorise the duplicate Order into a GroupOfOrders, you can easily do it if you don't extends 'List. It can be very difficult if you extendsList` and client classes use methods from it all over the code - it can be even worse if there are external clients from whom you don't control the code and usage of your class.
Just for the example, I defined the Order class (commande in english is order - It's just a matter of sharing with people, I don't mean you need to translate the code)
public class Order {
// properties, constructor...
public OrderResult executeOrder() {
// just do it
}
public String asXML() {
// generate the order as an XML string
}
}
public class GroupOfOrders {
private List<Order> orders = new ArrayList<>();
public void addOrder(Order o) {
// do some checking on order
orders.add(order);
}
public GroupedOrderResult executeAllOrders() {
GroupedOrderResult result = new GroupedOrderResult();
for (Commande c : commandes) {
OrderResult res = c.executeOrder();
result.add(c, res);
}
return result;
}
List<Order> getOrders() { return orders; }
}
And maybe, somewhere else in the program, when you need to get each order as an XML string:
GroupOfOrders orders; // initialised with the different orders
for (Order o : orders.getOrders()) {
String xmlOrder = o.asXML();
// do what needs to be done with xmlOrder
}
You will note that there is nowhere a need to cast.
Second, a few comments on the code you provided:
class Collection<T> extends ArrayList{}
This doesn't make sense: an ArrayList already implements Collection interface. May be you mean you have
List<T> lesCommandes = new ArrayList<Commande>();
this.commande1=new Commande(1,10,"filet 1kg",1,"10-12-2015","10-01-2016","en cours");
this.commande2=new Commande(2,15,"filet 5kg",1,"11-11-2015","10-02-2016","livrée");
this.commande3=new Commande(3,20,"caisse 10kg",2,"12-10-2015","10-03-2016","livrée");
this.lesCommandes.add(0, commande1);
this.lesCommandes.add(1, commande2);
this.lesCommandes.add(2, commande3);
Just do
lesCommandes.add(commande1); etc..
The List<T>$add(T) will actually add at the end of the list and manage the size dynamically.
xml=((Commande)this.lesCommandes.get(1)).xmlCommande();
If lesCommandes is defined as I suggest and there is a xmlCommande() method in the Commande class, then just do
xml = lesCommandes.get(1).xmlCommande();
My problem is as follows:
We have an Algorithm that works internally with
Expression-objects that have a "String getContent()" method
Manipulator-objects that manipulate on Expressions using the "Expression manipulate(Expression e)" method
This will become a framework in Java.
To solve a real problem, one needs to give a specific implementation
of both an Expression and a Manipulator and the Algorithm class will do the rest.
Let's say we need a ProblemExpression and a ProblemManipulator
for a specific problem.
The ProblemExpression may contain a lot of new fields,
which can be used by the ProblemManipulator.
Right now, I can only think of two ways to write clean code:
Let ProblemManipulator.manipulate assume its arguments are ProblemExpressions
Use instanceOf
But I've got the feeling this is not how I should do it.
Any other suggestions?
Regards and thank you in advance,
Xaero.
Sounds like you should use a Generic. Like
interface Manipulator<E extends Expression> {
public void manipulate(E expression);
}
class ProblemManipulator implements Manipulator<ProblemExpression> {
public void manipulate(ProblemExpression expression) {
// expression is a ProblemExpression
}
}
As "Problem" is a different problem, it can be an interface that extends Expression like so:
interface IProblemExpr extends Expression
{ //additional methods
}
class ProblemExpression implements IProbExpr
{
}
class ProblemManipulator()
{
ProblemManipulator(IProblemExpr expr)
{
..
}
}
Generics are not enough, if both ProblemExpresions and ProblemManipulators can be accessed publicly.
At first i thought some kind of factory framework would do the trick.
I.e., either Expressions need to be able to create Manipulators or vice-versa.
for example, say ProblemManipulators were private inner classes of ProblemExpressions - obtained from Expression#createManipulator(...).
However, this does not quite do the trick ... in the end, if the Algorithm is allowed to 'hold onto references to' both the Expression and Manipulator, and can obtain different unrelated implementations, then the Algorithm implementation can always (if incorrectly written) wind up invoking the wrong Manipulator for a given Expression - nothing can be done at compile time to prevent this runtime mistake as all Manipulators can be invoked with any Expression.
So, it seems to me that invocation of the Manipulator (or Expression) must 'go thru' the Expression (or conversely the Manipulator) thus ensuring that the correct Manipulator is invoked for the given Expression.
I.e., Expression needs 'manipulate()' method which delegates to the appropriate Manipulator.
I studied the way generics work, and I came up with the following solution:
First, I created a two classes, one for the expression and one for the manipulator:
public class ObjectExpression { }
public class ObjectManipulator <E extends ObjectExpression> {
public void calculate(Set<E> objects) {
... // Do something
}
}
Next, I created an Algorithm class, which is generic.
Two classes are needed:
Some expression
Something that manipulates this type of object
We get:
public class Algorithm <F extends ObjectExpression, E extends ObjectManipulator<F>> {
E om;
public Algorithm( E om ) {
this.om = om;
}
public void run(Set<F> objects) {
om.calculate(objects);
}
}
Then, I created an implementation for the String case:
we need an expression and a manipulator
public class StringExpression extends ObjectExpression {
}
public class StringManipulator extends ObjectManipulator<StringExpression> {
#Override
public void calculate(Set<StringExpression> objects) {
// Do String stuff
}
}
Then, we can run the Algorithm as follows for Objects:
Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>> algo1 = new Algorithm<ObjectExpression, ObjectManipulator<ObjectExpression>>(manipo);
Set<ObjectExpression> objects = new HashSet<ObjectExpression>();
... // fill set
algo1.run(objects);
And for Strings:
StringManipulator manips = new StringManipulator();
Algorithm<StringExpression, StringManipulator> algo2 = new Algorithm<StringExpression, StringManipulator>(manips);
Set<StringExpression> strings = new HashSet<StringExpression>();
... // fill set
algo2.run(strings);
To me, this seems an elegant solution.
What do you think?
Any alternatives/improvements?