I am writing a program with different classes and there there is a collection class which will store only the sub-classes of the superclass.
Okay, so i have an Order super class that stores quantity. The code snippet is like this:
abstract class Order { //superclass
private int quantity; //instance variables
public Items(int quantity) { //constructor
this.quantity = quantity;
}
public int getQuantity() { // instance method
return quantity;
}
public abstract double totalPrice();
Then i have sub-classes of the order class. The sub-classes are below.
class Coffee extends Order { //subclass
private String size; //instance variables
public Coffee (int quantity, String size) { //constructor
super(quantity);
this.size = size;
} //... some other methods
} // end of Coffee class
class Donuts extends Order { //sub-class
private double price; //instance variables
private String flavour;
public Donuts(int quantity, double price, String flavour) { //constructor
super(quantity);
this.price = price;
this.flavour = flavour;
} //...some other methods
} //end of donut class
class Pop extends Order {
private String size;
private String brand;
public Pop(int quantity, String size, String brand) {
super(quantity);
this.size = size;
this.brand = brand;
} //...again there are some other methods
} //end of pop sub-class
Now this is where i need help. I have written a collection class that contains ArrayList<>. The code snippet is this:
class OrderList {
private ArrayList<Order> list;
public OrderList() {
list = new ArrayList<Order>();
}
What i want to do in the collection class is to have instance methods that ensure that only sub-classes are only added to my collection class.*
What i have tried so far is this (which makes me a complete fool, i know that).
public void add(Coffee cof) {
list.add(cof);
}
public void add(Donut don) { // i know we cant have methods with the same name
list.add(don);
}
public void add(Sandwich sand) {
list.add(sand);
}
public void add(Pop p) {
list.add(p);
}
SO community can you please give me some hints on my problem.
You are getting your abstractions wrong. A Product .. isn't an Order.
A Product is simply a Product. It has some "identity", and probably different "flavors". But when you think about it, initially, it is not an order. An order comes into existence when a customer selects various products, puts them into some shopping card ... and hits the "order" button.
Just think how things are "in the real" world. And that is what should guide the model that you build.
Meaning: your Products should not subclass Order. Instead, you could be doing something like:
public abstract class ShopItem {
// that contains those things that all products in the shop have in common, like
public abstract double getPrice();
...
and then all your Products extend that class. It might be even more useful to avoid inheritance here completely, and turn ShopItem into an interface (that would depend if you really find good reasons to use an abstract class; in order to define common behavior of ShopItems).
Next:
public class ProductOrder {
private final ShopItem orderedItem ...
private final int quantity ...
And to bring things together:
public final class Order {
private final List<ProductOrder> allItemsOfAnOrder ...
Your method signature will be:
public void add(Order order){
...
}
because an Order can hold reference to any of its subtypes.
I don't really see the need for your own OrderList. Since Order is an abstract class, you can only add instances of non-abstract child classes to any List<Order> that you declare.
Also, instead of
class OrderList {
private ArrayList<Order> list;
public OrderList() {
list = new ArrayList<Order>();
}
}
you can also use
class OrderList extends ArrayList<Order> {
public OrderList() {
super();
}
}
and then simply use the add(Order element) that you inherited from your parent class.
But then again, it might be more convenient to just declare an ArrayList<Order> wherever you intended to use your OrderList, as long as you don't add any new methods (that are not given by a regular List) to justify having an extra class.
Related
Consider the following: say we have an IRestaurant and an IBooking interface.
We then have the following interface function:
interface IBooking {
void reserve(IRestaurant restaurant);
}
However, business requirements dictate a booking service in a country could make reservations to only restaurants in the same country. Then say we have in USA:
class USABooking implements IBooking { ... }
class USARestaurant implements IRestaurant { ... }
In this case, since reserve() in IBooking takes in any instance of IRestaurant, the USABooking implementation would be required to check the instance of the IRestaurant to see if it is an instance of a USARestaurant and then downcast. However, we could also do this as an alternative:
interface IBooking<R extends IRestaurant> {
void reserve(R restaurant);
}
class USABooking implements IBooking<USARestaurant> {
void reserve(USARestaurant restaurant) { ... }
}
Is this a recommended way to go about enforcing the type limitation? In other words, is this better than performing runtime checks on the restaurant instance types? The typing approach sounds good to me, but I just want to make sure it won't "blow up" the architecture and turn out to be a misuse or abuse, since there are other interfaces that also would require such limitations (e.g. ICuisine).
Here's another alternative since I don't understand why there are USABooking and USARestaurant classes:
Consider just having a Booking and Restaurant class, where Restaurant provides a getCountry() method. Separately, to avoid a proliferation of classes, a Booking instance might have something like a List<RestaurantBookingRule> - in this case there would be a single rule that checks the country of the Restaurant. For example:
public class Restaurant {
private final String country; // constructor omitted
public String getCountry() { return country; }
}
public interface RestaurantBookingRule {
public void validateRequest(Restaurant r); // throws exception if the rule is broken
}
public class RequiredCountry implements BookingRule {
private final String country; // constructor omitted
public void validateRequest(Restaurant r) {
if (!r.getCountry().equals(country))
throw ...
}
}
public class Booking {
private final List<RestaurantBookingRule> rules; // constructor omitted
public void reserve(Restaurant r) {
rules.forEach(r -> r.validateRequest(r));
...
}
}
then:
Restaurant r1 = new Restaurant("USA");
Restaurant r2 = new Restaurant("CAN");
Booking usaBooking = new Booking(List.of(new RequriedCountry("USA"));
usaBooking.reserve(r1); // ok
usaBooking.reserve(r2); // throws exception
I am working on a project about design patterns using Java. The class diagram before using the design patterns is provided in the link. Since I am new to Java, some of the classes methods descriptions is ambiguous for me.
For example in a class called Mall which has a method stores(), the method stores() is abstractly described as returning an "enumeration" of the stores in the mall (I'm using Java arrays as a placeholder in my example code).
I'd like to know what could be an "enumeration" in Java, i.e. what should I use for the concrete return type? In that particular case we are expected to use the Iterator design pattern. Please provide an example if possible.
https://www.dropbox.com/s/kbug0ow3e14284b/DP_Project_1182.pdf?dl=0
public class Mall {
private String mallId;
private Store[] Stores;
private Customer[] customers;
public void enter(Customer c){}
public void exit(Customer C){}
public ShoppingCart getShopingCart()
{
return new ShoppingCart();
}
public Customer[] customers()
{
}
public Store[] stores()
{
}
void addStore(Store S)
{
}
}
You need to create an abstract class called Store as per your objective.
To return Enumeration of Iterator type, I have created a List and returned its elements as an Iterator.
I hope this example helps:
public abstract class Store {
private String name;
private Item items;
//..other items
}
public class Mall {
private Store myStore;
//Vector which Stores all Store objects
private List<Store> listOfStores=new LinkedList();
//stores method which returns an Enumeration of Stores*/
public Iterator<Store> stores(){
return listOfStores.iterator();
}
public void addStore(Store s){
listOfStores.add(s);
}
}
public class ClassA_V01 {
private String name;
private int age;
// getter and setter
}
public class ClassA_V02 {
private String name;
private int age;
private int gender;
// getter and setter
}
public static void main(String[] args) {
SomeClass classA = new ClassA_V01();
classA.setName("myName);
classA.setAge(99);
performLogic(classA);
// OR
SomeClass classA = new ClassA_V02();
classA.setName("myName);
classA.setAge(99);
classA.setAge(1);
performLogic(classA);
}
public void performLogic(SomeClass classA) {
// do something
}
For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?
In my example, ClassA_V01 and ClassA_V02 are the same class except that one has more attribute "gender"
How does one implement the above such that classA can be equals to either ClassA_V01() or ClassA_V02?
"...For strategy pattern to work, both classes must implement the same methods defined in the interface. But what if the classes need to have different fields and methods?..." really this is not a criteria for strategy pattern.
Strategy pattern's intent is to identify and make family of algorithms interchangeable. If you read the pattern's documentation carefully, Strategy can be used when many related classes differ only in their behavior.
Appropriate decomposition is the key for better (extendable) design. A typical (but primitive) solution to Employee assignment, sub-classing tempEmp and permanentEmp types will put us in trouble and will not allow temp employee to become permanent in its life time (which has no meaning in real terms). This happens because we miss an important point- each employees employeeness is not different, they are all same type of employees with different pay policies. (same logic can be extended for Leave policy and so on)
This becomes simple if all types of employees have Salary computation based on same components (same state). But your question is what if TempEmployee gets only basicPay whereas PermanentEmployee gets basicPay as well as travelAllowance (additional attribute which is not present for TempEmp). This can be modeled by a combination of simple inheritance hierarchy along with strategy taking care of computation algorithm dependent upon Employee's (aka. Context) attribute (age)
public class Employee {
//name and id
private PayPackage payPackage;
private int age;
PayPackage strategy;
public double computeSalary() {
return payPackage.computePay(age);
}
//get/setPayPackage(...)
}
public abstract class PayPackage {
private double basicPay;
abstract public double computePay(int age);
protected double getBasicPay(){
return basicPay;
}
}
public class TempPayPackage extends PayPackage{
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 2000.00;
}
return getBasicPay() + veteranAllowance;
}
}
public class PermanentPayPackage extends PayPackage{
private double travelAllowance;
#Override
public double computePay(int age) {
double veteranAllowance = 0;
if (age > 40) {
veteranAllowance = 5000.00;
}
return getBasicPay() + travelAllowance + veteranAllowance;
}
}
Important thing to remember is Design patterns never work alone or as an alternative, they work hand in hand with Object oriented code and other patterns.
Hi I am a beginning programmer and I think I have a simple question but yet i can't find the answer. I hope you can help me:D I have four classes in total but what I need to solve is in class Person. I have a simple method that needs thePrice parameter from class Product. But it does not work because i can't get access to this parameter.
This is the method that the Person class uses to buy a product. The budget from a person has to be greater or equal to thePrice, if not > he can not buy the product. But he can only buy the product if he has not owned the product already.
public class Person{
private String name;
private double budget;
private ArrayList<Product> allPossessions;
private Product theProduct; //association with class product, I have all getters and setters etc.
// the method:::
public boolean Buy(Product p) {
if (hasProduct(null) == true) {
if (budget >= Product.getThePrice()) {
// getTheprice does not work, how do i get this working? How do i get this parameter from class product?
return true;
}
return false;
}
return false;
}
This is class Product where I need to have thePrice, to create the method.
public abstract class Product {
protected String Design;
protected int yearOfPurchase;
protected double thePrice;
}
Thank you for your time and forgive my broken english! Thank you:)
You should write a getter method for thePrice param inside Product class.
public double getPrice() {
return thePrice;
}
I want to build Data main class with subclasses DataClass1(with own subclass Item) and DataClass2 (with own subclass Item1).
public class Data{
public List<DataClass1> dataClass1List = new ArrayList<DataClass1>();
public List<DataClass2> dataClass2List = new ArrayList<DataClass2>();
public class DataClass1{
public String name;
public List<Item> itemList = new ArrayList<Item>();
public class Item{
public String n1;
public String n2;
public String n3;
}
}
public class DataClass2{
public String name;
public List<Item1> item1List = new ArrayList<Item1>();
public class Item1{
public String n5;
public String n6;
}
}
}
When I want to fill main class Data I use this code:
Data data = new Data();
Item itm = new Item;
itm.n1="1";
itm.n2="2";
itm.n3="3";
data.dataClass1List.itemList.add(itm);
and same for dataClass2List
All sub classes must be public
Is there better way to declare and filling up my class Data
Thanks!!!
p.s. Data class and its sub classes contain only variables not methods!
You seem to be confusing some concepts here.
There are no subclasses in your code. DataClass1 and DataClass2 are inner classes of Data, Item is an inner class of DataClass1 and Item1 is an inner class of DataClass2.
There's no visible need for them to be inner classes, and you're best off avoiding inner classes until you're sure you need them and likely until you know Java a bit better.
With these as inner classes, your proposed usage of them will not work, as they're non-static inner classes, and can only be created within the context of an instance of the outer class.
With the class definitions as they are, a translation of your posted usage would be approximately
Data data = new Data();
DataClass1 dc1 = data.new DataClass1();
Item itm = dc1.new Item();
itm.n1="1";
itm.n2="2";
itm.n3="3";
dc1.itemList.add(itm);
data.dataClass1List.add(dc1);
But this is really quite bad (and it may contain mistakes - I have bothered trying to compile it). Having classes with only fields and no methods, and adding data in this way is not a very object-oriented approach at all.
As WirthLuce noted in a comment, you should change the names to represent something in your domain, and create methods to make them do something appropriate rather than just holding data that is manipulated from outside.
Some suggesions:
You should use getter and setter to access the different fields.
public class SomeClass {
private String name;
[...]
public void setName(String name) {this.name = name;}
public String getName() {return name;}
[...]
}
Since the Data classes are public, do they need to be inner class?
To fix this you would need to move the different public class to different files.
All internal lists could be made `final`.
public final List<Item> itemList = new ArrayList<Item>();
You could make a constructor for the class Item.
public class Item {
public Item(String n1,String n2,String n3) {
this.n1 = n1;
this.n2 = n2;
this.n3 = n3;
}
[...]
}