I'm trying to create a Pizza menu. I have 3 classes,
PizzaBase (with get / set methods for the thickness of the base
[either thin or deeppan])
PizzaTopping, again with get / set methods
for the type of topping
Pizza, where my cost variable is stored and
used across the 3 classes using inheritance.
As a cost variable is used for the base, the topping and the overall pizza itself.
Now my question is this, how would I go about creating a Pizza object, which in turn creates 1 base object, and a few toppings objects, each with a price?
I can work out how to calculate an overall price, I'm just a bit stuck creating objects within objects.
public class PizzaTopping extends Pizza{
private String topping;
public String getTopping(){
return this.topping;
}
public void setTopping( String topping ){
this.topping = topping;
}
}
public class PizzaBase extends Pizza{
private String base;
public void setBase( String base ){
this.base = base;
}
public String getBase(){
return this.base;
}
}
public class Pizza {
private double cost;
public void setCost( double cost ){
this.cost = Math.abs(cost);
}
public double getCost(){
return this.cost;
}
public void makingPizza(){
PizzaBase b = new PizzaBase();
}
}
Replace the Pizza class with CostableItem class:
public class CostableItem {
private double cost;
public void setCost( double cost ){
this.cost = Math.abs(cost);
}
public double getCost(){
return this.cost;
}
}
Then extend it in both toppings and base:
public class PizzaBase extends CostableItem {...}
public class PizzaTopping extends CostableItem {...}
After that create a class called Pizza that has one base and multiple toppings:
public class Pizza{
private PizzaBase base;
private ArrayList<PizzaToppings> toppings;
//..
}
You don't need inheritance for this at all. At the most you might need an interface. So I would design it this way:
public interface PricedItem {
double getCost(); //double is suitable for our purposes
}
Since you want to calculate cost, everything that is a priced item should have a getCost() method. This will apply to your PizzaTopping, PizzaBase, and Pizza class:
public class PizzaTopping implements PricedItem
private String name;
private double cost;
public PizzaTopping(String name, double cost) {
this.name = name;
this.cost = cost;
}
...
#Override
public double getCost() {
return cost;
}
}
More or less the same thing for PizzaBase:
public class PizzaBase implements PricedItem {
private double cost;
...
}
Your Pizza class will also implement PricedItem. But what is also important is that you will have a collection of PizzaTopping instances; there is no inheritance here!
public class Pizza implements PricedItem {
private double cost;
private PizzaBase base;
private List<PizzaTopping> toppings;
public Pizza(double cost, PizzaBase base) {
this.cost = cost;
this.base = base;
toppings = new ArrayList<PizzaTopping>();
}
...
public void addTopping(PizzaTopping topping) {
//left as an exercise to the reader :)
}
#Override
public double getCost() {
//this is left as an exercise to the reader :)
return totalCost;
}
}
Related
I was going through adapter design pattern, and found we can allow us to collaborate with incompatible interface.
Now suppose, I found this example on stackoverflow.
public interface IWetherFinder {
public double getTemperature(String cityName);
}
class WeatherFinder implements IWetherFinder{
#Override
public double getTemperature(String cityName){
return 40;
}
}
interface IWeatherFinderClient
{
public double getTemperature(String zipcode);
}
public class WeatherAdapter implements IWeatherFinderClient {
#Override
public double getTemperature(String zipcode) {
//method to get cityname by zipcode
String cityName = getCityName(zipcode);
//invoke actual service
IWetherFinder wetherFinder = new WeatherFinder();
return wetherFinder.getTemperature(cityName);
}
private String getCityName(String zipCode) {
return "Banaglore";
}
}
Now in this case can't we add one more method to existing interface something Like below.
public interface IWetherFinder {
public double getTemperature(String cityName);
public double getTemperatureByZipcode(String zipCode);
}
class WeatherFinder implements IWetherFinder{
#Override
public double getTemperature(String cityName){
// some logic to get temp by city
return 40;
}
#Override
public double getTemperatureByZipcode(String zipCode){
String city = getCityName(zipCode);
//some logic to get the temp by city name
return 40;
}
private String getCityName(String zipCode) {
return "Banaglore";
}
}
i have to implement Pizza(American and Neapolitan) decoration pattern with 4 different toppings(Salami,Soudjouk,Onion,Pepper) which extends "TopingDecorator" class and out of them 3 will be added to pizza by "Add Pizza" command.However, the code does not add it to Pizza's TopingDecorator ArrayList. It should be something like below(I am trying to add Salami and Soudjouk to AmericanPan pizza(which extends PlainPizza class)):
AmericanPan a = new American();
Salami s = new Salami(a);
Soudjouk so = new Soudjouk(s);
Here is my PlainPizza class:
public class PlainPizza implements Pizza{
private int cost;
private String name;
private int orderID;
List<ToppingDecorator> topingsOfPizza;
public PlainPizza(int orderID){
this.orderID = orderID;
topingsOfPizza = new ArrayList<ToppingDecorator>();
}
public void addPizza(PlainPizza p) {
Pizza.allPizzas.add(p);
}
public List<ToppingDecorator> getTopingsOfPizza() {
return topingsOfPizza;
}
#Override
public int cost() {
// TODO Auto-generated method stub
return cost;
}
public int getOrderID() {
return orderID;
}
public String getName() {
return name;
}
#Override
public void addTopping() {
}
And here is my AmericanPan class:
public class AmericanPan extends PlainPizza{
// Class Instances
private final int cost = 5;
private String name;
// Constructor
public AmericanPan(int orderID) {
super(orderID);
this.name = "AmericanPan";
}
// Get Cost
#Override
public int cost() {
return cost;
}
// Get Name
public String getName() {
return name;
}
I am tryin to add Salami on American Pan in Salami class:
public class Salami extends ToppingDecorator{
private String name;
ToppingDecorator t;
public Salami(PlainPizza pizza) {
super(pizza);
this.name = "salami";
this.addToping();
}
#Override
public int cost() {
return super.cost() + 3;
}
#Override
public void addTopping() {
t = new Salami(pizza);
pizza.topingsOfPizza.add(t);
}
And I am trying to add it with code below in my function in main class which operates the whole process:
PlainPizza piz = new AmericanPan(orderID);
// Check The Toppings that Pizza contains
if(pizzatops.contains("soudjouk")){
soudjok = true;
}if(pizzatops.contains("salami")){
salami = true;
}if(pizzatops.contains("pepper")){
pepper = true;
}if(pizzatops.contains("onion")){
onion = true;
}
// Add Pizza according to Toppings
for(int g = 0;g<pizzatops.size();g++){
if(pizzatops.get(g).equals("salami")){
Salami s = new Salami(piz);
}else if(pizzatops.get(g).equals("pepper")){
Pepper p = new Pepper(piz);
}else if(pizzatops.get(g).equals("soudjouk")){
Soudjouk p = new Soudjouk(piz);
}
else if(pizzatops.get(g).equals("onion")){
Onion o = new Onion(piz);
}
}
Pizza.allPizzas.add(piz);
System.out.println("AmericanPan pizza added to order " + orderID);
You're going about this all wrong, with the decorator pattern you use different decorator classes to create different type of instances. In your case this means that you can't add multiple toppings to a pizza because the toppings are actually pizzas themselves, so Salami is a salami pizza and Pepper is a pepper pizza and not two toppings
If you want to add multiple toppings to one pizza then Decorator is not the right pattern.
Here is my simplified decorator implementation
interface Pizza {
int cost();
}
public class PlainPizza implements Pizza {
#Override
public int cost() {
return 10;
}
}
public abstract class ToppingDecorator implements Pizza {
private Pizza pizza;
public ToppingDecorator(PlainPizza aPizza) {
pizza = aPizza;
}
#Override
public int cost() {
return pizza.cost();
}
}
public class SalamiPizza extends ToppingDecorator {
public SalamiPizza(PlainPizza aPizza) {
super(aPizza);
}
#Override
public int cost() {
return super.cost() +3;
}
}
public static void main(String[] args) {
SalamiPizza p = new SalamiPizza(new PlainPizza());
System.out.print(p.cost());
}
I tnink, your implementation is wrong. Decorator pattern using interfaces, abstract classes.
Here
You can see, what is the right implementation with Java.
I am trying to understand and accomplish the task of trying to create a class that extends a generic class that accepts all types of classes. So far I have that working. I am trying to create a class that extends a generic holder class and have this class accept only specific objects.
Example, a class called "ComputerOrder" that will not accept an Apple or Orange object but only a ComputerPart or Peripheral object, such as Motherboard or Printer objects. Been stuck on this for 2 weeks. I can't for the life of me figure this concept out. Any help would be appreciated.
abstract class Product{
protected float price;
abstract float price();
public String toString() {
return "Price = " + String.valueOf(price) + " ";
}
}
class Apple extends Product{}
class Orange extends Product{}
class ComputerPart extends Product{
public ComputerPart(float p){
price = p;
}
public float price() {
return price;
}
}
class Motherboard extends ComputerPart{
protected String manufacturer;
public Motherboard(String mfg, float p) {
super(p);
manufacturer = mfg;
}
public String getManufacturer() {
return manufacturer;
}
}
class Peripheral extends Product{
public Peripheral(float p) {
price = p;
}
public float price() {
return price;
}
}
class Printer extends Peripheral{
protected String model;
public Printer(String model, float p) {
super(p);
this.model = model;
}
public String getModel() {
return model;
}
}
class Cheese extends Product{
public Cheese(float p) {
price = p;
}
public float price() {
return price;
}
}
class Cheddar extends Cheese{
public Cheddar(float p) {
super(p);
}
}
class GenericOrder<T>{
public ArrayList<T> storage = new ArrayList<T>();
private static int counter = 1;
public final int id;
public T obj;
public GenericOrder(){
id = counter;
counter++;
}
public void add(T item){
storage.add(item);
}
public T get(int in){
return obj;
}
public void getId(){
System.out.println(this.id);
}
public String toString(){
String ret = "";
Iterator<T> it = storage.iterator();
while (it.hasNext()) {
ret += it.next() + "\n";
}
return ret;
}
}
class ComputerOrder extends GenericOrder {
public void add(ComputerPart in){
if(in instanceof ComputerPart){
storage.add(in);
}
}
}
public class Tme2{
public static void main(String[] args){
ComputerOrder com = new ComputerOrder();
com.add(new Motherboard("bla", 3.33f))
}
}
You can do it like this:
class ComputerOrder<T extends ComputerProduct> extends GenericOrder<T> {
//...
}
Here, ComputerProduct is a class that extends Product and all your computer products like ComputerPart or Peripheral extend ComputerProduct. Similarly, you could create a class FoodProduct derived from Product, from which Apple, Orange and Cheese are derived:
class FoodOrder<T extends FoodProduct> extends GenericOrder<T> {
//...
}
The declaration <T extends ComputerProduct> is a type restriction, which ensures that all types of T are derived from ComputerPart, otherwise you will get a compiler error.
The ComputerOrder class is still generic, so you could instance an order for all computer products:
ComputerOrder order = new ComputerOrder<ComputerProduct>();
// Add peripherals, printers, motherboards...
// Apples, ... will throw compiler errors...
But you could also restrict it to peripherals only:
ComputerOrder order = new ComputerOrder<Peripheral>();
// Add peripherals, printers,...
// Apples, motherboards (ComputerProduct, but NOT Peripheral) will fail...
So this class is inheriting things from other classes which when the client class is used will run all of this.
So far my output is
Your drink choice was: The name of the drink :Black coffeeand its price is: 3.0and the size is :2
When I write in the parameters "Coffee coffee = new Coffee("Black coffee",1,2,"Mocha");" into the client class.
This isn't quite right and I also need to calculate the total but I can't figure out where I need to put that bit of code.
public class Drinks extends CoffeeShop {
private String name; // default name
private double price_per_oz= .10; // default price per oz
private int size = 6;// default value
public Drinks(){
super();
}
public Drinks(String name,double price_per_oz,int size){
this.name = name;
this.price_per_oz = price_per_oz;
this.size = size;
}
public String toString(){
return ("The name of the drink :"+ name +
"and its price is: "+price_per_oz+
"and the size is :"+ size );
}
public double getPrice(){
return price_per_oz*size;
}
//getter setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice_per_oz() {
return price_per_oz;
}
public void setPrice_per_oz(double price_per_oz) {
this.price_per_oz = price_per_oz;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
inherited class:
public class CoffeeShop {
public CoffeeShop(){
}
public static void main (String [] args){
Coffee coffee = new Coffee("Black coffee",1,2,"Mocha");
Tea tea = new Tea ("Hot", 10,12, "Earl Grey");
}
}
coffee class:
public class Coffee extends CaffeinatedDrinks {
private String type="drip"; // default type
public Coffee(){
super();
}
public Coffee(String name,double price_per_oz,int size,String type){
super(name,price_per_oz,size);// inherit these from parent
this.type = type; // make type available to use
System.out.println(" "+"Your drink choice was:"+ " " + this);
}
public double getPrice(){
if(6 == super.getSize()){ // if default size then use default price
return super.getPrice();
}
else if(12 == super.getSize()){ // otherwise charge them more
return super.getPrice()+0.5;
}
else{
//must be the large
return super.getPrice()+1;
}
}
}
Tea class:
public class Tea extends CaffeinatedDrinks {
private String flavor =" English Breakfast"; // default flavor
public Tea(){
super();//inherit parent class
}
public Tea (String name,double price_per_oz,int size,String flavor){
super(name,price_per_oz,size);
this.flavor = flavor;
//define flavor in constructor method
}
public double getPrice(){
if(6 == super.getSize()){
return super.getPrice();
}
else if(12 == super.getSize()){
return super.getPrice();
}
else{
//must be the large
return super.getPrice();
}
}
}
Caffeinated drinks class:
public class CaffeinatedDrinks extends Drinks {
public CaffeinatedDrinks(){
super();// inherit parent class Drinks
}
public CaffeinatedDrinks(String name,double price_per_oz,int size){
super(name,price_per_oz*3,size);// take the price per oz from parent function and multiply it by 3
}
}
public class NonCaffeinatedDrinks extends Drinks {
public NonCaffeinatedDrinks(){
super();// inherit parent class drinks
}
public NonCaffeinatedDrinks(String name,double price_per_oz,int size){
super(name,price_per_oz*2,size);// take the price per oz from parent function and multiply it by 2
}
}
expected out put is something like this:
Your drink order consists of:
water, size small, cost :$0.60
coffee, type mocha, size medium, cost: $2.30
tea, flavor earl grey size large, cost: $1.20
The total cost of your order is: $4.10
What code is needed for the main to access the getPrice() method ?
I can access the public enum type with the built in values(); function
but cant figure out how to print the prices , thanks
public enum Drink {
GUINNESS(Type.STOUT),
COLA(Type.COLA);
private Type type;
private Drink(Type type) {
this.type = type;
}
private enum Type {
STOUT {
#Override
public double getPrice() {
return 4.0;
}
},
COLA {
#Override
public double getPrice() {
return 2.0;
}
};
public abstract double getPrice();
}
}
You have to add a getter for the price in the Drink enum.
public double getPrice() {
return type.getPrice();
}
And then you can do:
Drink cola = Drink.COLA;
double price = cola.getPrice();
You can't access the private inner enum outside the public enum, you can however delegate the method:
public enum Drink {
GUINNESS(Type.STOUT),
COLA(Type.COLA);
private Type type;
private Drink(Type type) {
this.type = type;
}
public double getPrice() {
return type.getPrice();
}
private enum Type {
STOUT {
#Override
public double getPrice() {
return 4.0;
}
},
COLA {
#Override
public double getPrice() {
return 2.0;
}
};
public abstract double getPrice();
}
}
You define the same method in the enum Drink:
public double getPrice() {
return type.getPrice();
}
You can't, since another class can't see the nested enum at all. You could add a delegating copy to the top-level enum.