Assume that I used decorated design pattern for making a pizza. There are 3 type of ingredients that user can add his pizza. Mozarella, souce and vegetables. I prepared these classes and set the cost.
This is main code
public class PizzaFactory {
public static void main(String[] args) {
Pizza p = new TomatoSauce(new Mozarella(new PlainPizza()));
System.out.println(p.getIngredients());
}
}
This is interface
public interface Pizza {
public String getIngredients();
public int getCost();
}
This is base pizza
public class PlainPizza implements Pizza{
#Override
public String getIngredients() {
return "Pizza ";
}
#Override
public int getCost() {
return 5;
}
}
This is decorator class
abstract class IngredientDecorator implements Pizza{
protected Pizza tempPizza;
public IngredientDecorator(Pizza newPizza) {
this.tempPizza = newPizza;
}
public String getIngredients() {
return tempPizza.getIngredients();
}
public int getCost() {
return tempPizza.getCost();
}
}
One of ingredient class is
public class Mozarella extends IngredientDecorator{
public Mozarella(Pizza newPizza) {
super(newPizza);
}
public String getIngredients() {
return tempPizza.getIngredients() + " Mozarella";
}
public int getCost() {
return tempPizza.getCost() + 1;
}
}
Others are look like them.
Now, I want to take input from user to which ingradient they want. In order to input I will create pizza. They may want just plain pizza. But since, I create my pizza -> Pizza p = new TomatoSauce(new Mozarella(new PlainPizza())); like this. How can I create pizza dinamic? Do I have to check each condition with if-else or switch-case?
Related
i am trying to write a class which has an array of a subclass in the same project, and when i am trying to write a method that will add a new object to the array on condition that this object is not already in the array, and also if the specific cell is free, so the object will enter to the array.
but the problem is that i need to insert a variable to this method which is the copy constructor's object.
the problem is that in the subclass i don't know how to write the copy constructor.
so i will give a short example of 2 classes and you will show me how to write a copy constructor with them :
public class Food
{
private String _foodName;
public Food(String foodName)
{
_foodName=foodName;
}
public String getFoodName()
{
return _foodName;
}
public void showName()
{
System.out.println("The food's name is: " +_getFoodName());
}
}
public class Apple extends Food
{
private int _numOfApples;
public Apple(String name, int numOfApples)
{
super(name);
_numOfApples=numOfApples;
}
public Apple(Apple other)
{
????
}
}
how does the copy constructor should looks like ?
thank you for your help :)
By invoking the other constructor. Like,
public Apple(Apple other) {
this(other.getFoodName(), other._numOfApples);
}
I cannot help you properly because i cannot understand entirely what you are trying to do but at least i can help you correct some mistakes in your code:
public class Food
{
private String food;
public Food(String foodName)
{
food = foodName;
}
public String getFoodName()
{
return food;
}
public void showName()
{
System.out.println("The food's name is: " + getFoodName());
}
}
public class Apple extends Food
{
private int numOfApples;
public Apple(String name, int numberOfApples)
{
super(food);
numOfApples=numberOfApples;
}
public Apple(Apple copy)
{
this.name = copy.name;
this.numOfApples = copy.numOfApples;
}
}
Hope this helps.
I have two interfaces and two classes, Order class is parent of CoffeeBagOrder, There is no compiler error it just isn't displaying and I can't see why not
Order class:
public abstract class Order implements OrderInterface {
//variables
final static double SALES_TAX = 0.1; //not initialised by constructor
int unitWeight, numberOfUnits;
public Order() {
unitWeight=0;
numberOfUnits=0;
}
public Order(int unitWeight, int numberOfUnits) {
unitWeight=unitWeight;
numberOfUnits=numberOfUnits;
}
public void numberOfItems(int number) {
numberOfUnits=number;
}
public void unitWeight(int weight) {
unitWeight=weight;
}
}
CoffeeBagOrder class
public class CoffeeBagOrder extends Order implements Sales {
final static double PRICE_PER_KG = 5.55;
double salesBeforeTax;
double tax;
double totalSales;
public CoffeeBagOrder() {
}
public CoffeeBagOrder(int unitWeight, int numberOfUnits) {
super(unitWeight,numberOfUnits);
}
public double calculateSalesBeforeTax() {
salesBeforeTax= unitWeight*numberOfUnits*5.50;
return salesBeforeTax;
}
public double calculateSalesTax() {
tax=salesBeforeTax*0.10;
return tax;
}
public double calculateTotalSales() {
totalSales=salesBeforeTax+tax;
return totalSales;
}
//Override
public String toString() {
return "Price before tax: "+calculateSalesBeforeTax()+"\nTax: "+calculateSalesTax()+"\nTotal price: "+calculateTotalSales();
}
}
main
import java.util.Scanner;
public class Tester {
public static void main (String[] args) {
Scanner sc= new Scanner(System.in);
System.out.print("Enter number of bags sold: ");
int unitWeight=sc.nextInt();
System.out.print("Enter weight of bags in kilograms: ");
int numberOfUnits=sc.nextInt();
CoffeeBagOrder customer=new CoffeeBagOrder(unitWeight,numberOfUnits);
customer.toString();
}
}
I have omitted the interfaces but they are followed accordingly , thanks in advance, also I am unsure if I have efficiently written the constructors as they are both the same?
Change your Order class constructor like below (check this.):
public Order(int unitWeight, int numberOfUnits) {
this.unitWeight=unitWeight;
this.numberOfUnits=numberOfUnits;
}
You were not updating class field in constructor! It was assigning the parameter to itself.
And modify toString in CoffeeBagOrder like below (check annotation):
#Override
public String toString() {
return "Price before tax: "+calculateSalesBeforeTax()+"\nTax: "+calculateSalesTax()+"\nTotal price: "+calculateTotalSales();
}
Always use #Override annotation when you intend to override, to take it effect, which is best practice rather than calling toString() explicitly.
And print using
System.out.println(customer);
This question already has an answer here:
Decorator method, one Decorator type in Java
(1 answer)
Closed 5 years ago.
I am trying to make some pizza with the Decorator Pattern (bear with me):
Suppose I have the following:
interface Pizza {
public String makePizza();
}
class PlainPizza implements Pizza {
#Override
public String makePizza() {
return "Base Pizza";
}
}
And then I have a general decorator:
abstract class PizzaDecorator implements Pizza {
protected Pizza specialPizza;
public PizzaDecorator(Pizza specialPizza) {
this.specialPizza = specialPizza;
}
public String makePizza() {
return specialPizza.makePizza();
}
}
And two implementations of the decorator:
class SausageDecorator extends PizzaDecorator {
public SausageDecorator(Pizza specialPizza) {
super(specialPizza);
}
public String makePizza() {
return specialPizza.makePizza() + addSausage();
}
private String addSausage() {
return " + sausage";
}
}
class OliveDecorator extends PizzaDecorator {
public OliveDecorator(Pizza specialPizza) {
super(specialPizza);
}
public String makePizza() {
return specialPizza.makePizza() + addOlives();
}
private String addOlives() {
return " + olives";
}
}
The problem is that I am able to have duplicate decorators.
How can I change the structure of this code to add a "uniqueness" constraint - that is, each Decorator can appear as most once? (My pizza place doesn't allow customers to get double sausage, sorry!)
class PizzaMaker
{
public static void main (String[] args)
{
Pizza pizza = new SausageDecorator(new SausageDecorator(new OliveDecorator(new PlainPizza())));
System.out.println(pizza.makePizza());
}
}
Output: Base Pizza + olives + sausage + sausage
In order to add unique constraint, you could define an interface called UniqueTopping like :
public interface UniqueTopping {
public String getTopping();
public void addTopping();
}
and have your decorator classes, PlainPizza class implement it.
In your decorator class, have a private variable called topping and implement the getTopping(), addTopping() like below:
class SausageDecorator extends PizzaDecorator implements UniqueTopping {
private String topping = "";
public SausageDecorator(Pizza specialPizza) {
super(specialPizza);
}
public String makePizza() {
addTopping();
return specialPizza.makePizza() + " " + getTopping();
}
#Override
public String getTopping() {
return topping;
}
#Override
public void addTopping() {
if ( !specialPizza.getTopping().equals(getTopping()) ) {
topping = "sausage";
}
}
}
See that addTopping() adds only if the specialPizza that is passed in the constructor has a different topping.
The getTopping() just returns the topping that was added in addTopping().
Also your PlainPizza should implement the UniqueTopping to return empty topping like below:
class PlainPizza implements Pizza, UniqueTopping {
#Override
public String makePizza() {
return "Base Pizza";
}
#Override
public String getTopping() {
return "";
}
#Override
public void addTopping() {
}
}
I am trying to practice with Polymorphism and using classes. I wrote a superclass called Card. I then wrote 3 subclasses called: IDCard, CallingCard, and DriverLicense. I then wrote another class called Billfold which is supposed to contain slots for two of the cards.
I am supposed to write a BillfoldTester program which adds two objects of different subclasses to a Billfold object.
In BillfoldTester, a DriverLicense object and a CallingCard object are instantiated and added to a Billfold, which refers to these objects with Card references.
I don't really understand how to do this. I created two Card objects but I am trying to add it to my Billfold and it wont work. I tried Billfold a = new Card (x); but it's not right... Any help is much appreciated.
public class BillfoldTester
{
public static void main (String[]args)
{
Card x= new IDCard("Julie", 1995);
Card j= new DriverLicense("Jess", 1997);
//Having trouble trying to put the objects into my Billfold and print it.
}
}
public class Billfold extends Card
{
private String card1;
private String card2;
void addCard(String Card)//Not sure if this should be String
{
card1=Card;
}
}
public class Card
{
private String name;
public Card()
//This is my superclass
{
name = "";
}
public Card(String n)
{
name = n;
}
public String getName()
{
return name;
}
public boolean isExpired()
{
return false;
}
public String format()
{
return "Card holder: " + name;
}
}
public class IDCard extends Card
{
//This is one of my subclasses
private int IDNumber;
public IDCard (String n, int id)
{
super(n);
this.IDNumber=id;
}
public String format()
{
return super.format() + IDNumber;
}
}
The polymorphism example. Not sure if the functionally is exactly what you need, but you can see the whole idea (I hope). See the showAllFormat() method of Billfold class.
The whole point is inside different format() methods of the DriverLicense and IDCard. Depending on the 'real' (or initially assigned) object the different method will be called even if you just only refer to 'Card' class.
NOTE:
You didn't provide your DriverLicense implementation, and my is just from head. I have a bit different constructor to show this sub-classes may be totally different.
import java.util.ArrayList;
import java.util.List;
class Billfold {
List<Card> list = new ArrayList<Card>(10);
void addCard(Card card) // Q: Not sure if this should be String
// A: You would like to add a Card
{
list.add(card);
}
void showAllFormat() {
// go polymorphism !...
// when you call this general 'format()' you see the subclasses
// 'format()' is executed, not from 'Card' class
for(Card x: list) {
System.out.println(x.format());
}
}
}
class Card {
private String name; /* owner */
public Card() //This is my superclass
{
name = "";
}
public Card(String n) {
name = n;
}
public String getName() {
return name;
}
public boolean isExpired() {
return false;
}
public String format() {
return "Card holder: " + name;
}
}
class IDCard extends Card {
//This is one of my subclasses
private int IDNumber;
public IDCard(String n, int id) {
super(n);
this.IDNumber = id;
}
public String format() {
return "(ID)" + super.format() + " " + IDNumber;
}
}
class DriverLicense extends Card {
private String type;
public DriverLicense(String n, String type) {
super(n);
this.type = type;
}
public String format() {
return "(DL)" + super.format() + " TYPE: " + type;
}
}
public class BillfoldTester {
public static void main(String[] args) {
Card x = new IDCard("Julie", 1995);
Card j = new DriverLicense("Jess", "AB");
Billfold bf = new Billfold();
bf.addCard(x);
bf.addCard(j);
bf.showAllFormat();
}
}
This is wrong. A Billfold is not a Card; it HAS Cards.
public class Billfold
{
List<Card> cards = new ArrayList<Card>();
void addCard(Card card) {
if (card != null) {
this.cards.add(card);
}
}
}
Prefer composition over inheritance.
You should have Billfold class have two Card objects, not two Strings:
public class Billfold
{
Card card1;
Card card2;
void addCard(Card card) {
if (card != null) {
if (card1 != null) {
this.card1 = card;
} else {
this.card2 = card;
}
}
}
Ok, you're largely on the right track, just a couple of things:
void addCard(String Card)//Not sure if this should be String
{
card1=Card;
}
You're right, this should be:
void addCard(Card card)
{
card1=card;
}
then to add them:
public class BillfoldTester
{
public static void main (String[]args)
{
Card x= new IDCard("Julie", 1995);
Card j= new DriverLicense("Jess", 1997);
Billfold bf = new Billfold();
Billfold.addCard(x);
Billfold.addCard(j);
}
}
Then add a method to Billfold to print the cards in it.
Edit: Oh yeah, and duffymo is totally right, you don't need to extends Card on Billfold
I am a beginner in Java and i trying to understand the abstract classes.
Below is the code that I've written; the question is: how do i write a method that will return an instance of that class.
public abstract class VehicleEngine
{
protected String name;
protected double fabricationCons;
protected double consum;
protected int mileage;
public VehicleEngine(String n, double fC)
{
name = n;
fabricationCons = fC;
mileage = 0;
consum = 0;
}
private void setFabricationCons(double fC)
{
fabricationCons = fC;
}
public abstract double currentConsum();
public String toString()
{
return name + " : " + fabricationCons + " : " + currentConsum();
}
public void addMileage(int km)
{
mileage += km;
}
public double getFabricationConsum()
{
return fabricationCons;
}
public String getName()
{
return name;
}
public int getMileage()
{
return mileage;
}
//public VehicleEngine get(String name){
//if(getName().equals(name)){
//return VehicleEngine;
//}
//return null;
//}
}
public class BenzinVehicle extends VehicleEngine
{
public BenzinVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
if (getMileage() >= 75000) {
consum = getFabricationConsum() + 0.4;
} else {
consum = getFabricationConsum();
}
return consum;
}
}
public class DieselVehicle extends VehicleEngine
{
public DieselVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
int cons = 0;
if (getMileage() < 5000) {
consum = getFabricationConsum();
} else {
consum = getFabricationConsum() + (getFabricationConsum() * (0.01 * (getMileage() / 5000)));
}
return consum;
}
}
This is the main.
public class Subject2
{
public static void main(String[] args)
{
VehicleEngine c1 = new BenzinVehicle("Ford Focus 1.9", 5.0);
DieselVehicle c2 = new DieselVehicle("Toyota Yaris 1.4D", 4.0);
BenzinVehicle c3 = new BenzinVehicle("Citroen C3 1.6",5.2);
c1.addMileage(30000);
c1.addMileage(55700);
c2.addMileage(49500);
c3.addMileage(35400);
System.out.println(c1);
System.out.println(c2);
System.out.println(VehicleEngine.get("Citroen C3 1.6")); //this is the line with problems
System.out.println(VehicleEngine.get("Ford Focus "));
}
}
And the output should be:
Ford Focus 1.9 : 5.0 : 5.4
Toyota Yaris 1.4D : 4.0 : 4.36
Citroen C3 1.6 : 5.2 : 5.2
null
You can not return an instance of an abstract class, by definition. What you can do, is return an instance of one of the concrete (non-abstract) subclasses that extend it. For example, inside the VehicleEngine you can create a factory that returns instances given the type of the instance and the expected parameters, but those instances will necessarily have to be concrete subclasses of VehicleEngine
Have a look at the Factory Method pattern. Your concrete classes will implement an abstract method that returns a class instance.
Abstract classes do not keep a list of their instances. Actually no Java class does that. If you really want to do that, you could add a static map to VehicleEngine like this:
private static Map<String, VehicleEngine> instanceMap = new HashMap<String, VehicleEngine>();
and change your get method to a static one like this:
public static VehicleEngine get(String name) {
return instanceMap.get(name);
}
and add this line to the end of the constructor of VehicleEngine:
VehicleEngine.instanceMap.put(n, this);
this way every new instance created puts itself into the static map. However this actually is not a good way to implement such a functionality. You could try to use a factory to create instances, or you could consider converting this class into an enum if you will have a limited predefined number of instances.