I need some help on my class design or better said a reference to a common design pattern for a problem.
I am working in the aircraft industry. So far my programming skills are VBA and basic JAVA applications.
As an engineer my task is to create CAD Models for fixating components in and on to aircraft kitchens. To ensure a high reusability and to reduce development time I want to create a program which can recommend previous solutions.
Basically each aircraft operator can select from a catalog which galleys/kitchens (Monument) it would like to have installed. Inside these Monuments are multiple compartments. Inside a compartment we can install multiple equipment’s/components.
I would like to write a program which can tell me "you have installed these components together before -> In this compartment -> in that aircraft for that customer"
I have modeled the compartment, the monuments, and the aircraft. Each class extends form the same class BaseHolder:
public abstract class BaseHolder <I> {
private final ArrayList <I> heldItems = new ArrayList<I>();
public boolean addItem(final I i){
Objects.requireNonNull(i, "cannot add NULL");
return heldItems.add(i);
}
public boolean removeItem(I i){
return heldItems.remove(i);
}
public boolean contains(I i){
return heldItems.contains(i);
}
public int itemCount(){
return heldItems.size();
}
public boolean isEmpty(){
return heldItems.isEmpty();
}
public void Clear() {
heldItems.clear();
}
protected List<I> getHeldItems(){
return heldItems;
}
public I getElement(int n){
return heldItems.get(n);
}
}
public class Aircraft extends BaseHolder<Monument> {
// code
}
public class Monument extends BaseHolder<Compartment> {
private String name;
public Monument (String name){
this.setName(name);
}
// code
#Override
public boolean addItem(final Compartment c) {
Objects.requireNonNull(c, "cannot add NULL");
if (contains (c) ){
throw new IllegalArgumentException("Compartment already added!");
};
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(c.getName() ) ) {
throw new IllegalArgumentException("Compartment with an identical name already exits");
}
}
return getHeldItems().add(c);
}
public Compartment getCompartment(int n){
return getHeldItems().get(n);
}
public Compartment getCompartment(String name){
for(Compartment ctmp : getHeldItems()){
if (ctmp.getName().equals(name) ) {
return ctmp;
}
}
return null;
}
}
public class Compartment extends BaseHolder<IWeighable>{
private String name = "";
private double MAX_LOAD = 0.0;
public Compartment (String name ,final double max_load){
this.setName(name);
updateMaxLoad(max_load);
}
// code
protected double getTotalLoad(){
// code
}
/**
*
* #param load
* #throws InvalidParameterException if max load not >= than 0.0
*/
public void setMaxLoad(final double load){
if (load >= 0.0){
this.MAX_LOAD = load;
} else {
throw new InvalidParameterException("max load must be greater than 0.0");
}
}
public boolean isOverloaded(){
return (getTotalLoad() > MAX_LOAD ) ;
}
}
The problem I am having is that this design seems to have many flaws. Apart from it being rather tedious: getElement(n).getElement(n).getElement(n)
Adding elements to a compartment results in all aircrafts using the same compartment, having all the same equipment’s/components installed. As it is the same object in the DB. An instance of the compartment would be need. Cloning the DB Compartment before adding it to an aircraft is no option. I need to be able to change the allowable loads, a change it for all. To resolve this I thought of using some type of “wrapper” class as in:
public class MonumentManager {
public ArrayList <Monument> monuments = new ArrayList<>();
public ArrayList <LinkObect> links;
class LinkObect{
private Compartment c;
private IWeighable e;
LinkObect(Compartment c, IWeighable e){
this.c = c;
this.e = e;
}
}
public boolean addMonument(Monument m){
return monuments.add(m);
}
public void addElementToCompartment(IWeighable e, Compartment c){
boolean known = false; //to check if the passed compartment is known/handeld to/by the MonumentManager
for (Monument m : monuments){
if ( m.getCompartment(c.getName() ) != null ) known = true;
}
if (known){
links.add(new LinkObect(c, e));
} else {
throw new IllegalArgumentException("Compartment is not inside a managed Monument!");
}
}
public List<Compartment> whereUsed(IWeighable e){
// TODO
}
}
This class might solve the problem but it is feels odd. Can anybody point me in the right direction towards a common design pattern etc. I am reading a book from the local library on design patterns. But it seems to be slightly above me. (as is maybe my task).
Any suggestions / help etc would be highly appreciated.
I hope I'm understanding this correctly.
One thing is the Component you want to install that has certain characteristics and another thing is some representation of what you have installed.
The information of your installation does not need to be in your Component but in something else, let's call it Installation.
Your Installation has to know 2 things:
What kind of Component it is.
What other Installations it has inside.
The installation will look something like this.
public class Installation {
private Component type;
private List<Installation> content;
public Installation(Component type){
this.type = type;
this.content = new ArrayList<Component>();
}
//you can have methods for add, remove, etc...
}
Feel free to ask further clarifications.
Related
My goal is to use the Either class alongside my Human, Weapon, and Magazine classes.
These are the different Human declarations I want to test. (No weapon, no mag, and has all)
Human noWeapon = new Human(null);
Human noMag = new Human(new Weapon(null));
Human hasAll = new Human(new Weapon(new Magazine(2)));
Currently, I'm creating an Either in the following way:
Human noWeapon = new Human(null);
Either <String, Human> either2 = new Right <String, Human>(noWeapon);
Right <String, Human> either2_right = (Right<String, Human>) either2;
I'm struggling to understand the inner workings of the Either class and the ways for which I can use it for error handling. I want to be able to catch these errors when they occur so I can know when the error is happening
either2_right.getRight().getWeapon().getMag().getCount();
Currently, this is throwing a NullPointerException error for obvious reasons - but my goal is to instead catch the error and know when it occured.
My Either class is as follows:
abstract class Either<A, B> { }
class Left<A, B> extends Either<A, B> {
public A left_value;
public Left(A a)
{
left_value = a;
}
public A getLeft(){
return this.left_value;
}
public <B2> Either<A,B2> flatMap(final Function<B,Either<A,B2>> f){
return (Either<A,B2>)this;
}
public <B2> Either<A,B2> map(final Function<B,B2> f){
return (Either<A,B2>)this;
}
}
class Right<A, B> extends Either<A, B> {
public B right_value;
public Right(B b)
{
right_value = b;
}
public B getRight(){
return this.right_value;
}
public <B2> Either<A,B2> flatMap(final Function<B,Either<A,B2>> f){
return f.apply(right_value);
}
public <B2> Either<A,B2> map(final Function<B,B2> f){
return new Right(f.apply(right_value));
}
}
I'm using Either for my following 3 classes:
Human
class Human {
Weapon w;
public Human(Weapon w)
{
this.w = w;
}
public Weapon getWeapon()
{
return w;
}
}
Weapon:
class Weapon {
Magazine m;
public Weapon(Magazine m)
{
this.m = m;
}
public Magazine getMag()
{
return m;
}
}
Magazine:
class Magazine {
private int count;
public Magazine(int c)
{
count = c;
}
public int getCount()
{
return count;
}
}
Thank you for any help I'm able to get!
I'm struggling to understand the inner workings of the Either class and the ways for which I can use it for error handling.
Let us start with the second part of the question, how can I use Either for error handling?
Either can hold one of two values, for error handling you can declare a method to return an Either that will hold a valid computation result or an Exception. For example:
public Either<ArithmeticException, Double> divide (Double x, Double y) {
try {
return new Right<ArithmeticException, Double>(x/y);
} catch (ArithmeticException e) {
return new Left<ArithmeticException, Double>(e);
}
}
The caller will not get an ArithmeticException if he try to divide by zero, he will receive an Either holding the exception, in this example he will get a Left. The convention is to hold valid return results in a Right and the other results in a Left.
The implementation you provided doesn't make it easy for the caller to check if he got a Right or a Left or make it easy to process the result regardless of it is a Right or a 'Left a more complete implementation of Either here provides that convenience (for instance getOrThrow to get a Right value or throw an exception if the Either is not a Right).
To preface this, I've looked for numerous examples prior to asking and can't find any solution in regards to my problem.
I'm trying to implement a generic queue in a program I'm making, but stuck at a certain point. The program I've made is supposed to simulate a printer, queued with print jobs. There is a Queue class, PrintQueue class, and job class. (It is important to note the Job class consists of a job ID and String of who ordered it). I've included a function (in the printQueue class) where if the first job matches the job ID you put in, it will be deleted.
Unfortunately however, the queue is generic. This means I can't traverse the array with just an integer to check equality because it is a queue of job objects. To fix this I create a job with a blank name, and regular ID. The Job class has an equals method, which determines if either ID or Owner match, then it is true. But when I execute the code, this class is not called. The generic equals class is called instead, which will of course be false. After looking at many examples on this site, I tried all the recommended solutions, which did not work for me as my case (and problem) are different. What can I do to override the generic equals method? My code below is as simple as I could make it to reproduce this problem while keep context.
JOB CLASS
public class Job{
private String owner;
private int jobId;
public Job(String o, int j){
owner = o;
jobId = j;
}
public String getOwner(){
return owner;
}
public int getJobId(){
return jobId;
}
public String toString() {
return owner + " " + jobId + ". ";
}
public boolean equals(Job a) {
if(this.jobId == a.getJobId() || this.owner.equals(a.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
}
GENERIC QUEUE CLASS
import java.util.ArrayList;
public class Queue<T>{
private ArrayList<T> queue;
public Queue() {
queue = new ArrayList<T>();
}
public void enQueue(T obj1) {
queue.add(obj1);
}
public T deQueue() {
if(queue.size() != 0) {
T temp = queue.get(queue.size() - 1);
queue.remove(queue.size() -1);
return temp;
}
else
return null;
}
public int size() {
return queue.size();
}
public boolean isEmpty() {
if (size() == 0) {
return true;
}
else
return false;
}
public int positionOf(T a) {
for(int x = 0; x < queue.size(); x++) {
if(a.equals(queue.get(x))) {
System.out.println("Positionmatch");
return x;
}
}
return -1;
}
}
PRINTQUEUE CLASS
public class PrintQueue {
Queue<Job> prqueue = new Queue<Job>();
public PrintQueue() {}
public void lprm(int jobID) { //Removes the active job at the front of the queue if jobId matches, error message otherwise
//I can't JUST use jobID to check the position because the queue is a collection of JOBS not JobId's
if (prqueue.positionOf(new Job("",jobID))==0) {
prqueue.deQueue();
}
else if (prqueue.positionOf(new Job("",jobID))== -1) {
System.out.println("Job does not occupy first row.");
}
}
}
I know this is an extensive question, so if you do take the time to read it thank you very much. I wouldn't ask this if I could find the answer anywhere else.
Solution is simple: you are not overriding equals in your class, common mistake. Always annotate your methods with #Override so you can avoid this mistake.
Real equals method is taking an Object parameter, and yours has a Job as parameter, change that to Object and then cast it accordingly.
If you are using IDE I suggest right click -> source -> generate equals and you will see a good example how to do it.
You have to override your methods like this
#Override
public boolean equals(Object a) {
if(!(a instanceof Job))
throw new IllegalArgumentException();
Job job =(Job)a;
if(this.jobId == job.getJobId() || this.owner.equals(job.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
See also Why do I need to override the equals and hashCode methods in Java?
I have an interface namely Medicine and I created few instances for that. let's have a look,
interface Medicine {
Medicine Antibiotic = new Medicine() {
#Override
public int getCountOfTuberculous(QuarantineTwo quarantineTwo) {
return quarantineTwo.tuberculous().getSize();
}
/**
* Antibiotic cures the tuberculous
*
* #param q
*/
#Override
public void on(QuarantineTwo q) {
int initialNumOfTuberculous = getCountOfTuberculous(q);
System.out.println("Numbe of perople have Tuberculous before treated w/ Antibiotic = " + initialNumOfTuberculous);
q.tuberculous().changeHealthStatus(q.healthy());
}
#Override
public Treatment combine(Treatment treatment) {
return treatment.plus(this);
}
#Override
public String toString() {
return "Antibiotic";
}
};
Medicine Insulin = new Medicine() {
// cant use this method as it will provide the number of Tuberculous 0
// because, initially, the Quarantine was treated with Antibiotic
#Override
public int getCountOfTuberculous(QuarantineTwo quarantineTwo) {
return quarantineTwo.tuberculous().getSize();
}
#Override
public void on(QuarantineTwo q) {
if (isInsulinCombinedWithAntibiotic(q.getTreatment())) {
q.healthy().changeHealthStatus(q.feverish());
// q.healthy().changeHealthStatus(q.feverish(), iniNumOfTuberculous);
} else {
// Prevent None effects, done is this.combine
}
}
#Override
public Treatment combine(Treatment treatment) {
return treatment.remove(Medicine.None)
.plus(this);
}
/**
* helper method to see whether the Insulin is combined with Antibiotic
*
* #param treatment
* #return
*/
private boolean isInsulinCombinedWithAntibiotic(Treatment treatment) {
return treatment.contains(this) &&
treatment.contains(Medicine.Antibiotic);
}
#Override
public String toString() {
return "Insulin";
}
};
void on(QuarantineTwo quarantineTwo);
Treatment combine(Treatment treatment);
int getCountOfTuberculous(QuarantineTwo quarantineTwo);
}
Now, when I'm testing I may call like this,
#Test
public void antibioticPlusInsulin() throws Exception {
quarantine.antibiotic();
quarantine.insulin();
assertEquals("F:3 H:1 D:3 T:0 X:0", quarantine.report());
}
The two lines of codes means that we combined the treatment procedures with both the antibiotic and insulin to the Quarantine system and affect should be accumulative.
quarantine.antibiotic();
quarantine.insulin();
And, hence, I would like to keep a track of how many people are cured with Antibiotic initially from the Tuberculous stored in the initialNumOfTuberculous and use that value to make the call
q.healthy().changeHealthStatus(q.feverish(), iniNumOfTuberculous);
This call suppose to change the all the people from healthy state to feverish but the ones initially cured with Tuberculous.
How to store the value of the iniNumOfTuberculous inside the Medicine Antibiotic and make it available in the Medicine Insulin ?
Sounds like you need an abstract class
abstract class AbstractMedicine implements Medicine {
protected int iniNumOfTuberculous;
}
public class Insulin extends AbstractMedicine {
// can use iniNumOfTuberculous here
}
Note: The availability of the variable definition is shared; the value itself is not.
I don't think you should implement your concrete classes inside an interface, by the way
I wrote an abstract superclass distribution as folows, it contains a constructor, and two methods.
public abstract class Distribution
{
public Distribution(){}
public abstract void setParameters(HashMap<String,?> hm);
public abstract int getSample();
}
Hereafter, I wrote 4 subclasses ( Poisson, Geometric, Deterministic and Binomial ). These subclasses all look the same and are like this;
public class Binomial extends Distribution
{
BinomialDistribution distribution;
public Binomial()
{
super();
}
#Override
public void setParameters(HashMap<String,?> hm)
{
try
{
int n = 0;
double p =0.0;
if (hm.containsKey("n"))
if (hm.containsKey("p"))
p = Double.parseDouble((String) hm.get("p"));
else
throw new Exception("Exception: No p-value found");
else
throw new Exception("Exception: No n-value found");
distribution = new BinomialDistribution(n,p);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
#Override
public int getSample()
{
return distribution.sample();
}
}
In another class I want to use these classes. I want to give a HashMap to the Distribution.setparameters method, and let the program decide which subclass that fits the parameters given in that HashMap.
If I want to define A distribution the other class, this doesn't seem to work.
Distribution arrivalLength1distr = new Distribution();
Can somebody tell me what I do wrong and how my problem could be solved ?
Thanks !
let's imagine the following situation: I want to design a bidding application (like ebay) with the composite design pattern
I create an abstract superclass like "BidComponent" (which has getName()) and two subclasses "Article" and "Category".
Category has a List which can contain other BidComponents, Article does not implement a List but a getPrice() method.
If I want to iterate through this structure and I want to print out the Category-Article-Structure I need instanceof:
if(element instanceof Article){
Article article = (Article)element;
System.out.println(article.getName() + ":" + article.getPrice());
}else{
Category category = (Category)element;
System.out.println(category.getName());
}
This seems pretty wrong to me. Is there a better way to realise this (So without always checking the type via instanceof)? I ask this question because I read several times that using instanceof is bad design...
//Edit to mention my problem with Visitors:
Ok. But let's imagine I want to search the highest bid to all products. So I have
public class HighestBidVisitor implements BidComponentVisitor{
private double highestBid = 0d;
public HighestBidVisitor(Category category){
visitCategory(category);
}
#Override
public void visitCategory(Category category){
Iterator<BidComponent> elementsIterator = category.iterator();
while(elementsIterator.hasNext()){
BidComponent bidComponent = elementsIterator.next();
//Now I have again the problem: I have to check if a component in the Categorylist is an article or a category
if(bidComponent instanceof Article) visitArticle((Article)bidComponent);
else visitCategory((Category)bidComponent);
}
}
#Override
public void visitArticle(Article article){
if(article.getPrice() > highestBid) highestBid = article.getPrice();
}
}
But now I have the same problem again (See comment in visitCategory). Or am I doing this wrong?
You want to use the visitor pattern.
public interface BidComponentVisitor {
void visitArticle(Article article);
void visitCategory(Category category);
}
Then your BidComponent class would have a visit method:
public abstract void visitChildren(BidComponentVisitor visitor);
The Composite and Visitor patterns often work together.
Edit: The key to avoiding instanceof when using the vistor pattern is how you implement the visitChildren method. In Category you would implement it like this:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.visitCategory(this);
for (BidComponent child : children) {
child.visitChidren(visitor);
}
}
Since Article has no children, it's implementation is simpler:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.visitArticle(this);
}
They key is each concrete class in the composite pattern knows it's own type, so it can call the specific visitor method that has a parameter with it's specific type.
One variation is to have enter and exit methods in the visitor for any class with children:
public interface BidComponentVisitor {
void visitArticle(Article article);
void enterCategory(Category category);
void exitCategory(Category category);
}
With the above interface, Category.visitChildren() would look like this:
#Override
public void visitChildren(BidComponentVisitor visitor) {
vistor.enterCategory(this);
for (BidComponent child : children) {
child.visitChidren(visitor);
}
vistor.exitCategory(this);
}
To print the tree, you could do something like this:
public class PrintingVisitor implements BidComponentVisitor {
private int depth = 0;
private void printIndent() {
for (int i = 0; i < depth; i++) {
System.out.print(" ");
}
}
public void visitArticle(Article article) {
printIndent();
System.out.println(article.toString());
}
public void enterCategory(Category category);
printIndent();
System.out.println(category.toString());
depth++;
}
public void exitCategory(Category category) {
depth--;
}
}
The disadvantage of the visitor patter is your visitor class needs to either hardcode every possible subclass, or have a generic visitOther() method.
You are doing the visitor implementation wrong. The different Components handle their own dispatching of elements. They know what type they are so you don't need to do any instanceof checks.
public interface Visitor{
void visit(Article a);
void visit(Category c);
}
abstract class BidComponent{
...
abstract void accept(Visitor v);
}
public class Category{
....
public void accept(Visitor v){
v.visit(this); // visit Category
for(Article a : getArticles()){
v.visit(a); //visit each article
}
}
}
Then a visitor to find the highest bid
public class HigestBidVisitor implements Visitor{
private final double highest;
void visit(Category c){
//no-op don't care
//or we could track which Category we have visited last
//to keep track of highest bid per category etc
}
void visit(Article a){
highest= Math.max(highest, a.getPrice());
}
}
Then to search all:
HigestBidVisitor visitor = new HighestBidVisitor();
BidComponent root = ...
root.accept(visitor);
double highest = visitor.getHighestPrice();
I can't think of any clean solution right now. You might have to update your implementation to either store Article and Category instances separately.
With your current implementation where a List<BidComponent> needs to be traversed and each element needs to be processed based on it's type, this approach can be a bit better:
abstract class BidComponent {
public abstract String process();
}
class Category extends BidComponent {
#Override
public String process() {
return getName();
}
}
class Article extends BidComponent {
#Override
public String process() {
return getName() + " " + getPrice();
}
}
List<BidComponent> list = ..;
for (BidComponent c : list) {
System.out.println(c.process());
}
Another way to decouple the processing logic from the classes/objects is:
Map<Class<?>, Function<BidComponent, String>> processors = new HashMap<>();
processors.put(Category.class, Category::getName());
processors.put(Article.class, a -> a.getName() + " " + a.getPrice());
List<BidComponent> list = ..;
for (BidComponent c : list) {
System.out.println(processors.get(c.getClass()).apply(c));
}
Note that this uses Java 8 lambdas but the same can be implemented with Java 7 or lower by using your own interface (similar to Function) or the ones provided by Guava or Apache Commons.