Casting vs Duplicate Code: What is the best of two given options? - java

The situation (UML given below): A java package shall have a class Process that runs a calculation in a loop within a thread and notifies observers about the result of that calculation. A new calculation is initiated bei adding a value from outside the class to a queue the thread can read:
public class Process
{
/* ... */
Thread th;
BlockingQueue queue = new ArrayBlockingQueue(10);
public void calc()
{
th = new Thread(new Runnable()
{
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
try
{
Integer value = (Integer) queue.take();
List<Float> result = calculator.calcAllResults(value);
/* ... Do something with result ...*/
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}).start();
}
public void addValue(Integer value)
{
queue.add(value);
}
/* ... */
}
The calculation itself in calcAllResults(int value) is as follows: The calculator object has a (interchangeable by a config file, not fixed) list of "smaller calculators" that calculate exactly one Float in the result list. Now, the calculator object first gathers some data and then just runs all the small calculators in a loop:
public class Calculator
{
/* ... */
private DataGatherer1 dataGatherer1;
public List<Float> calcAllResults(int value)
{
List<Float> result = new List<Float>();
DataType1 dt1 = dataGatherer1.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt1));
}
}
/* ... */
}
My Problem: For the moment there is only one way to calculate the result, but in future there will be more. That means: Currently, the small calculator objects that run calcSingleResult depend on data of type DataType1 (see listing above), but in future there might be another set of calculator objects that depend on data of type DataType2. Of course, then there must be another class, DataGatherer2, that gathers data of that new type. In order to make the code expandable in the way mentioned, I thought of two options how to design the package. But none of them seem to be satisfactory for the reasons mentioned below. To make the two approches clear, I made two UML-Diagrams:
Design1
Design2
Design 1:
The calculator for calculating the result list has an AbstractDataGatherer object which can be of type DataGatherer1 or DataGatherer2 (depending on the state of the program). As both data types (DataType1 and DataType2) are of type AbstractDataObject, the method calcAllResults() can have all the logic for gathering data and calculation (an advantage of this design (?)), no matter what set of CalcType's is in its calculator list:
public class Calculator
{
/* ... */
private AbstractDataGatherer dataGatherer;
private List<AbstractCalculationType> calculators;
public List<Float> calcAllResults(int value)
{
List<Float> result = new List<Float>();
AbstractDataObject dt = dataGatherer.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt));
}
}
/* ... */
}
The disadvantage is (in my eyes) that a specific CalcType expects a specific DataType in its calcSingleResult()-routine. So AbstractDataObject dt must be casted. For example:
public class CalcType1A extends AbstractCalculationType
{
/* ... */
private DataType1 data;
public float calcSingleResult(AbstractDataObject data)
{
this.data = (DataType1) data;
}
/* ... */
}
Design 2:
The calcAllResults()-method is now inside an object of type AbstractCalculationStrategy. From this abstract class two (in future possibly more) subclasses exist: CalculationStrategy1 and CalculationStrategy2. Both define calcAllResults() alone. For example:
public class CalculationStrategy1 extends AbstractCalculationStrategy
{
/* ... */
private DataGatherer1 dataGatherer1;
private List<AbstractCalculationType1> calculators;
public float calcAllResult(int value)
{
List<Float> result = new List<Float>();
DataType1 dt1 = dataGatherer1.getData(value);
for (int i = 0; i < calculators.size(); i++)
{
result.add(calculators.get(i).calcSingleResult(dt1));
}
}
/* ... */
}
(The same for CalculationStrategy2, but with a DataGatherer2 object and AbstractCalculationType2 objects instead.)
This is basically the situation from above where only one calculation type existed. The advantage here is that each strategy must gather a specific data type that its calculator objects really wants (no cast). The disadvantage is that you have duplicate code: The logic in the method calcAllResult() is the same (or: must in future be implemented in the same way) for both (in future possible more) calculation strategies. Additionally the UML diagram shows that there is a symmetry that I would like to prevent with OOP-means, because OOP is made to prevent duplicate code / symmetry, right?
So, what is the best design? Or are both options not okay?

Related

Using arrayList pointers instead of multiple loops?

I am trying to write a program that contains many classes and in one class called "Dorm",I have an arrayList of Blocks,and in the "Block" class,I have an arrayList of Rooms,and in the "Room" class,I have an arrayList of "Students".
I am trying to access the number of available rooms(the rooms that at least have one empty space) through another class called the "Manager class". I have been told that I can just create another arrayList in the manager class to be used as a pointer and search up the empty rooms of the whole dormitory.
My question is,how is this going to work?
ps:This is what I wrote:
public static void availableRooms() { //Shows the available rooms in the dormitory.
Dorms dormitory = new Dorms();
Room room1 = new Room();
for(int i=0;i<dormitory.getBlocks().size();i++)
for(int j=0;j<Block.getRoomList().size();j++) {
if(!(room1.getStudentList().get(room1.getRoomCapacity()).equals(null)))
System.out.print("/t" + room1.getStudentList().get(i) + "/t");
}
}
My code isn't complete yet,so I'm not sure if it works...
Could you share your code/tentative? and clearly specify what's not working?
This being said, unless tied to specific constraints, one should make use of encapsulation and single responsibility principle (see SOLID on wiki) by keeping implementation details private and delegating tasks to the more relevant classes.
You may have something like:
class Dorm {
private List<Block> blocks = ...
...
public int getAvailableRooms() {
int total = 0;
for (Block b : blocks) {
total += b.getAvailableRooms();
}
return total;
}
}
class Block {
private List<Room> rooms = ....
...
public int getAvailableRooms() {
int total = 0;
for (Room r : rooms) {
if (! r.isFull()) {
total++;
}
}
}
class Room {
private int capacity = ...
private List<Student> students = ..
...
public boolean isFull() {
return capacity == students.size();
}
}
Where the Manager class, holding (an) instance(s) of Dorm, just make use of the getAvailableRooms() method which behind the scene delegate to the underlining Blocks and aggregate result... and so on.

How to find object with biggest attribute value in ArrayList (using different classes)

Java beginner here. I'm supposed to find the best result a participant has in an event (and later compare this result to others to find the winner etc).
I made classes for an event (with list of event results) , participant (with list of participant's total results), and result (with event obj, participant obj and result (double)) + a program class for the commands.
So far I have written a method that returns a participant's best result in an event as a double, but I need to return the entire result object instead. Not sure which class should be responsible for this (?) but I put this method in the event class for now.
public double getBestResultDouble(Participant p) {
double best = 0;
if (hasResult(p)) {
for (Result r : eventResults) {
if (p.equals(r.getParticipant())) {
double res = r.getResult();
if (res > best) {
best = res;
}
}
}
}
return best;
}
Simply save the corresponding (best) result as another local variable and return that at the end:
public Result getBestResultDouble(Participant p) {
double best = 0;
Result bestResult = null;
if (hasResult(p)) {
for (Result r : eventResults) {
if (p.equals(r.getParticipant())) {
double res = r.getResult();
if (res > best) {
best = res;
bestResult = r;
}
}
}
}
return bestResult;
}
Try to think a little more in terms of OOP (Object-Oriented Programming).
A Participant can participate in multiple Event's. Everytime a Participant participates in an Event, there is a Result that gets generated for that particular Participant and gets a corresponding score.
Now that I have the basic structure of how I want to layout my classes, so we can define specific behavior of how we want each class to go about.
public class Participant
{
private List<Event> events;
private String name;
public Participant( String name )
{
this.name = name;
events = new ArrayList<Event>();
}
//... other methods
public void participate( Event event )
{
double score;
//... get the score
events.add( event );
event.recordResult( this, score );
}
}
So now the Participant can participate in certain Event's that you define.
Now looking at what I did in that participate method, we need to have a way to store Result's inside of an Event.
public class Event
{
private List<Result> results;
public Event()
{
results = new ArrayList<Result>();
}
// ...
public void scoreResult( Participant participant, double score )
{
//if a participant cannot participate multiple times in an event, probably need a check to see if
//the participant is already in the list, otherwise update the score isntead of adding a new Result
results.add( new Result( participant, score ) );
}
}
So now each Event that you define has a way to score a Result for a particular Participant.
I'll just do the basic outline for a Result class
public class Result
{
private Participant participant;
private double score;
public Result( Participant participant, double score )
{
this.participant = participant;
this.score = score;
}
// ... getters and setters
}
This could be a basic outline for your Objects. Now you can define a method in Participant to get the best Result of all Event's he has participated in. Something like:
public Result getBestResult()
{
Result bestResult = null;
for( Event event : events )
{
if( bestResult == null )
bestResult = event.getResult();
if( bestResult.getScore() < event.getResult().getScore() )
bestResult = event.getResult();
}
//if the participant hasn't participated in any event, then this will return a null result.
return bestResult;
}
I hope that this makes sense and will help you think about things in a more OO way. This way you can define other methods for Event such as how to get the Participant with the highest Result.
Of course this is just one way to layout the classes, and I highly encourage you to try to think ahead of time how you want your objects to interact with each other before coding. Think about relationships between objects. I know you are just a beginner, so this might be a little advanced, but if you are serious about learning how to code efficiently, this is definitely something to look into.
In Java, the most common way is to create an instance of Comparator<Result>, which compares instances of Result. You delegate the comparison to the Comparator instead of comparing yourself.
You can then use standard Java methods to do your sorting.
Standard:
List<Result> = ....
Comparator<Result> cmp = ....;
list.sort(cmp);
Result max = list.get(0);
With Streams
List<Result> = ....
Comparator<Result> cmp = ....;
Result max = list.stream().max(cmp);
Double is already Comparable, so you can code your Comparator like:
Comparator<Result> cmp = new Comparator() {
public int compare(Result r1, Result r2)
{
return r1.getResult().compareTo(r2.getResult());
}
}

Should i create a class that implements an interface or use the interface as it is? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
In this server app i am extending there is a class EventManager with a method:
pubic void addEvent(Event event, int time){ // code to process handling of events }
Event is and interface. I have several classes in which i need to run a very similar event that uses a lot of the same methods. Rather than rewriting each of those methods in each of the classes that i am running similar events in, i thought that if i created public class that implements event and had each of the methods in it:
public class someEvent impements Event{
public void send(String message){
for (int i = 0; i < Server.playerHandler.players.length; i++) {
if (Server.playerHandler.players[i] != null) {
if (Server.playerHandler.players[i].inPcGame()) {
Client c = (Client)Server.playerHandler.players[i];
c.sendMessage(message);
}
}
}
}
public void spawn(int[] npcs, wave){
int x = 4234;
int y = 2343;
int z = 1;
int health = 10 * wave;
int maxHit = 5 * wave ;
int attack = 150;
int defence = 200;
NpcHandler.getNpcHandler().spawnNpc(c, 1, x, y, z, 0, health, maxHit, attack, defence, true, false);
}
// Event method override
public void executeEvent(){
spawn(npcList, waveNum);
send(message);
}
}
Then use to then create objects in each of the class am running the events in. Then pass those objects to the EventManager.
I taught myself and am still learning, my friend who also taught himself, but has been programming longer says i should do that and should do this instead:
import sever.event.EventManager;
public class someClass {
public void send(String message){
for (int i = 0; i < Server.playerHandler.players.length; i++) {
if (Server.playerHandler.players[i] != null) {
if (Server.playerHandler.players[i].inPcGame()) {
Client c = (Client)Server.playerHandler.players[i];
c.sendMessage(message);
}
}
}
}
public void spawn(int[] npcs, wave){
int x = 4234;
int y = 2343;
int z = 1;
int health = 10 * wave;
int maxHit = 5 * wave ;
int attack = 150;
int defence = 200;
NpcHandler.getNpcHandler().spawnNpc(c, 1, x, y, z, 0, health, maxHit, attack, defence, true, false);
}
EventManager.getSingleton().addEvent( new Event(){
public void executeEvent(){
spawn();
send();
}}, 12000
);
}
and do this in each class rewriting each of the methods in each class i use the event in.
He insists that my way uses more memory and is CPU intensive. I do not understand how my way is heavier on the CPU instead of less intensive than his way. Which way is the correct way and why?
maybe you're sorta right and your friend's sorta wrong, though
maybe you're sorta wrong and your friend's sorta right, though
what you want is utility methods in a base class:
what your friend likely wants is for the event manager to have the closure in case of an exception:
Events are exactly the same event every time. They can be the only impetus for a programme; you want to see them up front.
class AWholeProgram {
static EventManager E = new EventManager();
public static void main(String[] args) {
E.add ( new PhoneCall("15555551212") );
E.add( PrintBatteryLevel );
E.add( PlaySong );
E.add( WaitForIncomingCall );
}
// so the "events", the only things that can happen, are up front...
final static Event PrintBatteryLevel = ...;
final static Event PlaySong = ...;
final static Event WaitForIncomingCall = ...;
final static Event PhoneCall = new phoneCall("15555551212")...;
class phoneCall extends Event {
long number = Long.parseString("15555551212");
phoneCall( String s ) {
//convert to digits, and look in the phone book, and see if its long distance, etc.
}
public void fireEvent() {
// makes the phone call
}
}
}
It makes a big difference where the phone number is. If it is tucked away in the event manager class, hehe...
Its really obvious what the program does, also, its really obvious what the program could do,
and better yet, its really obvious that the program doesn't do anything else.
Many programs kick off with the gui, frames packing and whatnot, and way over in some bit of handler there's a button, which, if clicked deletes a file, or worse. ouch..
You likely want all the events in one file. Yikes.
like this...
class BaseEvent {
// every event logs
public void fireEvent( Event e ) {
log.print( event );
}
String toString() {
return getClass.getName();
}
}
class PlayerEvent extends BaseEvent {
player p; // every player event has an associated player (and logs, and has a toString method..)
public void fireEventWithPlayer( Player x, Game g ) {
g.spawn( x );
super.fireEvent( this ); ///
}
}
class GameEvents implements BaseEvent {
startGame, endGame, createGame, ...
}
/// just where should the spawn event be?
/// then add the event manager,
/// a main method that goes through all the steps, so you can see how your logs will look...
/// and at the end pre-define all your events.
/// you'll have **lots** of events in categories (player, game, network, etc.)
Answer to question?
implementing an interface the way your friend suggests is almost identical to creating an anonymous inner class which is in scope at the point of declaration. a new instance is created for each call and the quantity of data passed with the "interface method" is dependent on the quantity of data that is in scope at the declaration.
with predefined events the data is low and the cpu is fast. More classes is better than more definitions.
The JVM can optimize the cats off a rug if you declare stuff far enough in advance. Your friend is right, if your were writing in C, or an untyped dynamic language, or even a JVM that couldn't optimize well. Syntactically, you need to keep in mind that the event will run in the event manager's run thread and not at the point where the object is defined.
Your method has two variables
addEvent(Event event, int time)
how will it work with a different signature?

How to use writeStringArray() and readStringArray() in a Parcel

I recently came across a very stupid (at least from my point of view) implementation inside Androids Parcel class.
Suppose I have a simple class like this
class Foo implements Parcelable{
private String[] bars;
//other members
public in describeContents(){
return 0;
}
public void writeToParcel(Parcel dest, int flags){
dest.writeStringArray(bars);
//parcel others
}
private Foo(Parcel source){
source.readStringArray(bars);
//unparcel other members
}
public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>(){
public Foo createFromParcel(Parcel source){
return new Foo(source);
}
public Foo[] newArray(int size){
return new Foo[size];
}
};
}
Now, if I want to Parcel a Foo Object and bars is null I see no way to recover from this situation (exept of catching Exceptions of course). Here is the implementation of these two methods from Parcel:
public final void writeStringArray(String[] val) {
if (val != null) {
int N = val.length;
writeInt(N);
for (int i=0; i<N; i++) {
writeString(val[i]);
}
} else {
writeInt(-1);
}
}
public final void readStringArray(String[] val) {
int N = readInt();
if (N == val.length) {
for (int i=0; i<N; i++) {
val[i] = readString();
}
} else {
throw new RuntimeException("bad array lengths");
}
}
So writeStringArray is fine if I pass bars which are null. It just writes -1 to the Parcel. But How is the method readStringArray supposed to get used? If I pass bars inside (which of course is null) I will get a NullPointerException from val.length. If I create bars before like say bars = new String[???] I don't get any clue how big it should be. If the size doesn't match what was written inside I recieve a RuntimeException.
Why is readStringArray not aware of a result of -1 which gets written on null objects from writeStringArray and just returns?
The only way I see is to save the size of bars before I call writeStringArray(String[]) which makes this method kind of useless. It will also redundatly save the size of the Array twice (one time for me to remember, the second time from writeStringArray).
Does anyone know how these two methods are supposed to be used, as there is NO java-doc for them on top?
You should use Parcel.createStringArray() in your case.
I can't imagine a proper use-case for Parcel.readStringArray(String[] val) but in order to use it you have to know the exact size of array and manually allocate it.
It's not really clear from the (lack of) documentation but readStringArray() is to be used when the object already knows how to create the string array before calling this function; for example when it's statistically instanciated or it's size is known from another previously read value.
What you need here is to call the function createStringArray() instead.

How to label edges with probabilities in graph using Jung 2

I am fairly new to Java and Jung. I am writing a program where I need to add probabilities on edges of the event occurrence(means probability of the event that data will flow from first node to other). I am a little confuse that will Max-Flow do the trick for me or do I need to use some other option or there is no option to do it within Jung and in that case do I need to write it on my own? Any help in this regard will be appreciated.
regards,
waqas
Do you intend to set the edge weights to represent the probabilities of certain events? The Max-Flow algorithm will use the "capacities" you assign to each edge to find the path of maximum flow from the source vertex to the sink vertex. What exactly are you trying to do here?
I'm not very sure what your final aim is, so I'll try my best to help out.
You can first represent the probabilities by defining a custom Edge and Edge Factory classes. What I did was:
0. Imports:
import org.apache.commons.collections15.Factory;
1. Add in your custom classes. They custom edge class might be something like:
public static class MyEdge {
private int flow;
private int capacity;
private String name;
private int eIndex;
public MyEdge(String name, int eIndex) {
this.name = name;
this.eIndex = eIndex;
}
public int getCapacity() {
return this.capacity;
}
public void setCapacity(int edgeCapacity) {
this.capacity = edgeCapacity;
}
public int getFlow() {
return this.flow;
}
public void setFlow(int edgeFlow) {
this.flow = edgeFlow;
}
public String toString() {
return this.name;
}
}
The custom edge factory is what actually creates your edges each time you draw them on the canvas graphically, it might look like:
public static class MyEdgeFactory implements Factory {
private static int defaultFlow = 0;
private static int defaultCapacity = 0;
private int edgeCount;
private MyEdgeFactory() {
}
public MyEdge create() {
String name = "E" + edgeCount;
MyEdge e = new MyEdge(name, edgeCount);
edgeCount++;
e.setFlow(defaultFlow);
e.setCapacity(defaultCapacity);
return e;
}
}
2. Tell your visualization viewer how to display the edge labels; you'll need to add this in wherever you're creating your graph and VisualizationViewer object (vv):
vv.getRenderContext().setEdgeLabelTransformer(new Transformer() {
public String transform(MyEdge e) {
return (e.toString() + " " + e.getFlow() + "/" + e.getCapacity());
}
});
Now everytime you create an edge, it's label will be of the form "E0 0/0", "E1 0/0" and so on.
I'll be posting detailed tutorials and code on my blog soon so you could watch that space if you're going to be spending significant time on whatever project you're working on.
Look at the way you're calling setEdgeLabelTransformer, you need to pass it a new Transformer(), like I've done in my code snippet numbered 2.
When you pass a new ToStringLabeller(), you're telling the viewer to label using the toString() method of the edge object. You'll need to pass a custom Transformer instead, just correct your code to look like mine and you'll be fine.

Categories

Resources