I got a product object with two attributes which I want to oberserve with two different oberservers. But if I only change one attribute I also get a notification from the other attribute observer that it got changed. How can I make sure to only get a notification when it really got changed?
import java.util.Observable;
public class Product extends Observable {
private String name;
private double price;
public void setName(String n){
name = n;
this.setChanged ();
this.notifyObservers();
}
public void setPrice(double p){
price = p;
this.setChanged ();
this.notifyObservers();
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
public class ObserverDemo {
public static void main(String [] args) throws Exception {
Product p1 = new Product();
p1.addObserver((obj, arg) -> System.out.println("Name was changed to: " + ((Product) obj).getName()+"\n"));
p1.addObserver((ob, arg) -> System.out.println("Price was changed to: " + ((Product) ob).getPrice()+"\n"));
p1.setPrice(1.95);
p1.setName("Milk");
p1.setName("Banana");
p1.setPrice(0.95);
}
}
Any change on the observable class will notify all the registered observer classes. You can use the argument in the notifyObservers method to identify the change and create only one observer object.
import java.util.Observable;
public class Product extends Observable {
private String name;
private double price;
public void setName(String n){
name = n;
this.setChanged ();
this.notifyObservers("Name was changed to " + n + "\n");
}
public void setPrice(double p){
price = p;
this.setChanged ();
this.notifyObservers("Price was changed to " + p + "\n");
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
public class ObserverDemo {
public static void main(String [] args) throws Exception {
Product p1 = new Product();
p1.addObserver((obj, arg) -> System.out.println(arg));
p1.setPrice(1.95);
p1.setName("Milk");
p1.setName("Banana");
p1.setPrice(0.95);
}
}
Yes thats what I thought of first, but I am supposed to do it with 2 observers. I have absolutely no idea how to solve that..
Related
I have a simple pizza program in Java, made using the Factory Pattern.
Basically, when a factory is given as a parameter, it creates a particular pizza, which is then added to the list of pizzas of the PizzaShop.
I would like to create a method that displays how many particular pizzas I have. For instance, when the method is called, I would like it to display something like "We have 5 PizzaChicago and 3 PizzaNewYork". I am not sure how to do that.
This is my code.
public interface Pizza {
String name();
}
public class PizzaChicago implements Pizza{
public Integer price;
public PizzaChicago(Integer price){
this.price = price;
}
#Override
public String name() {
return this.getClass().getSimpleName();
}
}
public class PizzaNewYork implements Pizza{
public Integer price;
public PizzaNewYork(Integer price){
this.price = price;
}
#Override
public String name() {
return this.getClass().getSimpleName();
}
}
public interface PizzaFactory {
public Pizza createPizza(Integer price);
}
public class PizzaNewYorkFactory implements PizzaFactory{
#Override
public Pizza createPizza(Integer price) {
return new PizzaNewYork(6);
}
}
public class PizzaChicagoFactory implements PizzaFactory{
#Override
public Pizza createPizza(Integer price) {
return new PizzaChicago(8);
}
}
import java.util.ArrayList;
import java.util.List;
public class PizzaShop {
List<Pizza> pizzaList = new ArrayList<>();
public void createPizza(PizzaFactory factory, Integer price){
Pizza pizza = factory.createPizza(price);
System.out.println(pizza.name() + " " + "was created");
pizzaList.add(pizza);
}
}
`
What you have to do is iterate the list and check what is the type of every object.
int countPizzaNewYork = 0, countPizzaChicago = 0;
for(Pizza p: pizzaList){
if(p instanceOf PizzaNewYork)
{
countPizzaNewYork++;
}
else
{
countPizzaChicago++;
}
}
System.out.println("We have "+ countPizzaChicago+" PizzaChicago and "+countPizzaNewYork+" PizzaNewYork");
Alternate approach (use Map instead of a List):
public class PizzaShop {
Map<String, Integer> pizzaDiary = new HashMap<>();
public void createPizza(PizzaFactory factory, Integer price) {
Pizza pizza = factory.createPizza(price);
System.out.println(pizza.name() + " " + "was created");
int previousCount = pizzaDiary.getOrDefault(pizza.name(), 0);
pizzaDiary.put(pizza.name(), previousCount + 1);
}
}
Use the pizzaDiary map to print out your pizza counts.
Having a separate class for each pizza could be problematic and somewhat cumbersome. And for certain using the class name and instanceof is not the way to go. Have you considered using an Enum to represent the Pizzas? Here is an example of how it might work.
public class PizzaShopDemo {
enum Pizza {
CHICAGOPIZZA(8, "Chicago Pizza"),
NEWYORKPIZZA(6, "New York Pizza");
private double price;
private String name;
private int count = 0;
private Pizza(double price, String name) {
this.price = price;
this.name = name;
}
public double getPrice() {
return price;
}
public String getName() {
return name;
}
public void update() {
count++;
}
public int getCount() {
return count;
}
}
public static void main(String[] args) {
new PizzaShopDemo().pizzaShop();
}
public void pizzaShop() {
createPizza(Pizza.CHICAGOPIZZA);
createPizza(Pizza.NEWYORKPIZZA);
createPizza(Pizza.CHICAGOPIZZA);
createPizza(Pizza.NEWYORKPIZZA);
createPizza(Pizza.CHICAGOPIZZA);
createPizza(Pizza.CHICAGOPIZZA);
createPizza(Pizza.NEWYORKPIZZA);
for (Pizza p : Pizza.values()) {
System.out.println(p.getName() + ", " + p.getPrice()
+ ", " + p.getCount());
}
}
public void createPizza(Pizza type) {
type.update();
// other stuff here.
}
}
Prints
Chicago Pizza, 8.0, 4
New York Pizza, 6.0, 3
I am a java beginner and I am trying to get used to objects. Is there anyway that I can print out the value of a constructor in main? How can I print out the value's Kevin,20? Thanks
public class MainConstructor {
public static void main(String[] args) {
ConstructorClass emp1 = new ConstructorClass("Kevin", 20);
}
}
//Constructor Class
public class ConstructorClass {
private String name;
private int number;
public ConstructorClass(String name, int number) {
this.name = name;
this.number = number;
System.out.println("called");
}
}
Add a toString() method to ConstructorClass:
public String toString() {
return name + "," + number;
}
Then call this from main:
public static void main(String[] args) {
ConstructorClass emp1 = new ConstructorClass("Kevin",20);
System.out.println(emp1.toString());
}
Try using toString() in your class
public String toString() {
return this.name + "," + this.number;
}
and in your main just do emp1.toString(); to print it to your console
Constructor is basically just another method (but for the love of what is holy, never say that during interview or even to your professor) so there is nothing wrong with doing this:
public class ConstructorClass {
private String name;
private int number;
public ConstructorClass(String name, int number) {
this.name = name;
this.number = number;
System.out.println(name+" "+number);
}
}
But this solution is really ugly and kind of "hotfixy". Better solution would be to have constructor to only get the values and have separate method to print what you want:
public ConstructorClass(String name, int number) {
this.name = name;
this.number = number;
}
void printNameAndNumber() {
System.out.println(name+" "+number);
}
And use the class like this in your main
ConstructorClass c = new ConstructorClass("John",85)
c.printNameAndNumber();
Also some people like to handle this by going through hoops and loops and overriding ToString, but that is being too overzealous and there is really no benefit in your case (or any other primitive case).
public ConstructorClass(String name, int number) {
this.name = name;
this.number = number;
System.out.println(name + "," + number);
}
If you want to properly print out those values, you should have getter methods set in your methods
Example below
public String getName(){
return name;
}
public int getNumber(){
return number;
}
Then to print those values, you should then use methods toString() and method print() to display your values
Example
public String toString(){
return getName() + " " + getNumber();
}
public void print(){
System.out.println(toString());
}
Then in the class with the main method, you call your print method for that specific class
Example
ConstructorClass emp1 = new ConstructorClass("Kevin",20);
emp1.print();
Hope this helped, Enjoy :)
This is my first post on stack exchange so i'm not really sure what you need but here's my issue:
I am creating an inventory tracker for my java class and I am running into an issue where I can't use the method addItem(Item newItem) because the class Inventory isn't static and does not have a constructor. We have a UML Diagram
we are supposed to work off of and it doesn't include a constructor for Inventory and says nothing about static.
I'm not really sure what else you need but any help would be greatly appreciated!
Thanks!
public class InventoryTrackerInterface {
public Inventory inv;
public static void main(String[] args) {
//test item
Item b1 = new Item("abc",1,123,"01345");
}
}
public class Inventory {
private Item[] itemArray;
private int totalItems = 0;
public int getTotalNumberOfItems() {
return totalItems;
}
public Item getItem(int index) {
if (index < 0 || index >= totalItems) {
return null;
} else {
return itemArray[index];
}
}
public void addItem(Item newItem) {
if (newItem == null) {
System.out.println("Item not added.");
} else {
itemArray[totalItems] = newItem;
totalItems++;
}
}
public void saveInventoryToFile(String fileName) {
}
public void loadInventoryFromFile(String fileName) {
}
}
public class Item {
private String name;
private int quantity;
private double price;
private String upc;
private Item() {
}
public Item(String name, int qty, double price, String upc) {
}
public String getName() {
return name;
}
public int getQuantity() {
return quantity;
}
public double getPrice() {
return price;
}
public String getUPC() {
return upc;
}
}
You do not need to explicitly define a constructor in order to instantiate a class. In such cases, a default constructor is automatically created.
UML diagrams will usually only indicate constructors in cases where you would need one with parameters, as in the case of Item.
You can either define your inv property as static:
public class InventoryTrackerInterface
{
public static Inventory inv;
public static void main(String args[])
{
// Test items
Item b2 = new Item("abc",1,123,"01345");
Item c2 = new Item("dfe",2,456,"56789");
// Inventory object
inv = new Inventory();
inv.addItem(b2);
inv.addItem(c2);
}
}
Or access it through an InventoryTrackerInterface instance:
public class InventoryTrackerInterface
{
public Inventory inv;
public static void main(String args[])
{
// Test items
Item b2 = new Item("abc",1,123,"01345");
Item c2 = new Item("dfe",2,456,"56789");
InventoryTrackerInterface instance = new InventoryTrackerInterface();
// Inventory object
instance.inv = new Inventory();
instance.inv.addItem(b2);
instance.inv.addItem(c2);
}
}
I want to make an array of objects and use it in different functions. I wrote this pseudocode
privat stock[] d;
privat stock example;
public void StockCheck(){
d =new stock[2];
d[0]= new stock("a","test1", 22);
d[1]= new stock("b","test2", 34);
}
#Override
public stock getStock(String name) throws StockCheckNotFoundException{
int i;
System.out.println("ok" + name + d.legth); // error
example = new stock("example","example",2);
return example;
}
In class test I make an instance of getStock and I call the function getStock stock.getStock();
I get a NullPointerExeption when I do d.length. d is null but I don't understand why.
Hmmmm. If that is in any way like your real code, then the problem is that your "constructor" isn't really a constructor, as you've declared it to return void, making it an ordinary method instead. Remove tbat "void" and it may fix the problem!
Perhaps this example of code will do what you need, using three classes
Test - the main test code
Stock - the implied code for Stock from your question
StockCheck - the corrected code from your question.
(Note: you may really want to use an ArrayList inside StockQuote so you can add and delete Stocks.)
Test class
package stackJavaExample;
public class Test {
public static void main(String[] args) {
String[] testNames = {"test1","test2","notThere"};
StockCheck mStockCheck = new StockCheck();
for (int i=0; i<testNames.length; i++) {
Stock result = mStockCheck.getStock(testNames[i]);
if (result == null) {
System.out.println("No stock for name: " + testNames[i]);
} else {
System.out.println("Found stock: " + result.getName() + ", " + result.getSymbol() + ", " + result.getValue());
}
}
}
}
Stock class
package stackJavaExample;
public class Stock {
private String symbol;
private String name;
private double value;
public Stock(String symbol, String name, double value) {
this.symbol = symbol;
this.name = name;
this.value = value;
}
public String getSymbol() { return symbol;}
public String getName() { return name;}
public double getValue() {return value;}
}
StockCheck class
package stackJavaExample;
public class StockCheck {
private Stock[] d;
public StockCheck() {
d = new Stock[2];
d[0] = new Stock("a","test1", 22);
d[1] = new Stock("b","test2", 34);
}
public Stock getStock(String name) {
for (int i=0; i < d.length; i++) {
if (d[i].getName().equalsIgnoreCase(name)) {
return d[i];
}
}
return null;
}
}
Sorry if this is a little confusing, First time using this site so I dont know if I entered my code in right or not. So my question is, when I run this program in class driver I get this:
name: No Name Yet
Manufacturer: no name yet
Engine Cyclinders: 0
Load: 0.0
Towing: 0.0
Which is the default, now I am trying to be able to put a input in the class driver that will change say the name to whatever I set it as from class Person for example. I have tried doing p.setName("Tim") but it will only show the name as tim if I call the writeouput method from class Person. If I call the writeoutput from class Truck then it says no name yet. I put super in the writeoutput but I'm not sure what i'm doing wrong. any help would be appreciated
public class Person {
private String name;
public Person()
{
name = "No Name Yet";
}
public Person(String initialName)
{
name = initialName;
}
public void setName(String newName)
{
newName = "tim";
name = newName;
}
public String getName()
{
return name;
}
public void writeOutput()
{
System.out.println("name: " + name);
}
public boolean hasSameName(Person otherPerson)
{
return this.name.equalsIgnoreCase(otherPerson.name);
}
}
public class Vehicle extends Person {
String manufactName;
int engine;
public Vehicle()
{
manufactName = "no name yet";
engine = 0;
}
public Vehicle(String initialManufactName, int initialEngine)
{
manufactName = initialManufactName;
engine = initialEngine;
}
public void setManufactName(String newManufactName)
{
manufactName = newManufactName;
}
public void setEngine(int newEngine)
{
engine = newEngine;
}
public String getManufactName()
{
return manufactName;
}
public double getEngine()
{
return engine;
}
public void writeOutput()
{
super.writeOutput();
System.out.println("Manufacturer: " + manufactName);
System.out.println("Engine Cyclinders: " + engine);
}
public boolean hasSameManufactName(Vehicle otherVehicle)
{
return this.manufactName.equalsIgnoreCase(otherVehicle.manufactName);
}
public boolean hasSameEngine(Vehicle otherVehicle)
{
return this.engine == (otherVehicle.engine);
}
}
public class Truck extends Vehicle {
private double load;
private double towing;
public Truck()
{
load = 0;
towing = 0;
}
public Truck(double initialLoad, double initialTowing)
{
load = initialLoad;
towing = initialTowing;
}
public void setLoad(double newLoad)
{
load = newLoad;
}
public void setTowing(double newTowing)
{
towing = newTowing;
}
public double getLoad()
{
return load;
}
public double getTowing()
{
return towing;
}
public void writeOutput()
{
super.writeOutput();
System.out.println("Load: " + load);
System.out.println("Towing: " + towing);
}
public boolean hasSameLoad(Truck otherTruck)
{
return this.load == (otherTruck.load);
}
public boolean hasSameTowing(Truck otherTruck)
{
return this.towing == (otherTruck.towing);
}
}
public class Driver extends Truck{
public static void main(String[] args){
Person p = new Person();
Vehicle v = new Vehicle();
Truck t = new Truck();
t.writeOutput();
}
}
You don't need to create an instance of each class in the hierachy.
Try:
Truck t = new Truck();
t.setName("tim");
t.writeOutput();
Also, your design is odd: Vehicles wouldn't normally subclass a Person, and a Driver wouldn't normally subclass a Truck. A Driver would be a subclass of a Person. A Truck would be a subclass of a vehicle and a Vehicle would "have" a Driver.