Issue
I work in a small program using the Observable pattern. The code that I can't modify is provided below.
public abstract class ObservableStock {
private double price;
private StockType name;
public ObservableStock(StockType name) {
this.name = name;
}
protected ObservableStock() {
}
public StockType getName() {
return name;
}
public void setPrice(double price) {
this.price = price;
}
public abstract void notifyPriceChange(double price);
public abstract void registerStockExchangeCenter(ObserverStockExchangeCenter oc);
}
public abstract class ObserverStockExchangeCenter {
protected Map<StockType, Double> ownedStock;
public ObserverStockExchangeCenter() {
this.ownedStock = new HashMap<>();
}
public void buyStock(ObservableStock s) {
ownedStock.put(s.getName(), 0.0);
System.out.println("Helo");
}
//assume we won't change values in the map
public Map<StockType, Double> getOwnedStock() {
return ownedStock;
}
public abstract void observe(ObservableStock o);
public abstract void notifyChange(StockType type, double price);
}
public enum StockType {
Amazon,
Google,
}
I can modify the classes provided below:
public class ObservableStockImpl extends ObservableStock {
private ObserverStockExchangeCenter exchangeCenter;
public final StockType stockType;
public ObservableStockImpl(StockType name) {
this.stockType = name;
}
public void notifyPriceChange(double price) {
this.exchangeCenter.getOwnedStock().put(stockType, price);
this.exchangeCenter.notifyChange(stockType, price);
}
public void registerStockExchangeCenter(ObserverStockExchangeCenter oc) {
this.exchangeCenter = oc;
}
public StockType getStockType() {
return stockType;
}
}
public class ObserverStockExchangeCenterImpl extends ObserverStockExchangeCenter {
private final List<ObservableStockImpl> observableStocks;
public ObserverStockExchangeCenterImpl() {
super();
observableStocks = new ArrayList<>();
}
public void notifyChange(StockType type, double price) {
for (ObservableStockImpl os : observableStocks) {
if (os.getStockType().equals(type)) {
os.setPrice(price);
os.notifyPriceChange(price);
}
}
}
public void observe(ObservableStock o) {
observableStocks.add((ObservableStockImpl) o);
}
@Override
public void buyStock(ObservableStock s) {
ObservableStockImpl stock = (ObservableStockImpl) s;
ownedStock.put(stock.getStockType(), 0.0);
}
}
However, I failed to pass all the tests which are below:
@Test
public void stockPriceChangeTest(){
ObservableStock amazonStock = new ObservableStockImpl(StockType.Amazon);
ObserverStockExchangeCenter NYStockCenter = new ObserverStockExchangeCenterImpl();
NYStockCenter.buyStock(amazonStock);
Map<StockType, Double> boughtStocks = NYStockCenter.getOwnedStock();
assertEquals(1, boughtStocks.size());
assertEquals(0,boughtStocks.get(StockType.Amazon),0);
amazonStock.setPrice(5);
Map<StockType, Double> boughtStocks2 = NYStockCenter.getOwnedStock();
assertEquals(1, boughtStocks2.size());
// failing below
assertEquals(5,boughtStocks2.get(StockType.Amazon),0);
}
The issue is stock price increase not reflected in the code. Can anyone help me to find what is the issue here?
Solution
As we discussed on the comments, here's the working code after the updates.
Problems:
- you were not calling
notifyPriceChange
atsetPrice
exchangeCenter
was not initialized/set at ObservableStockImpl
BONUS Feedback:
- get rid of
ObservableStockImpl
class. You are actually duplicating though you are "extending"ObservableStock
Look for comments starting with // GT
below for the updates i made:
package temp;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class StockListenerTest {
@Test
public void stockPriceChangeTest() {
ObservableStock amazonStock = new ObservableStockImpl(StockType.Amazon);
ObserverStockExchangeCenter NYStockCenter = new ObserverStockExchangeCenterImpl();
amazonStock.registerStockExchangeCenter(NYStockCenter); // GT 1
NYStockCenter.buyStock(amazonStock);
Map<StockType, Double> boughtStocks = NYStockCenter.getOwnedStock();
assertEquals(1, boughtStocks.size());
assertEquals(0, boughtStocks.get(StockType.Amazon), 0);
amazonStock.setPrice(5);
Map<StockType, Double> boughtStocks2 = NYStockCenter.getOwnedStock();
assertEquals(1, boughtStocks2.size());
// failing below
assertEquals(5, boughtStocks2.get(StockType.Amazon), 0);
}
}
abstract class ObservableStock {
private double price;
private StockType name;
public ObservableStock(StockType name) {
this.name = name;
}
protected ObservableStock() {
}
public StockType getName() {
return name;
}
public void setPrice(double price) {
this.price = price;
notifyPriceChange(price); //GT 2 - called notifyPriceChange
}
public abstract void notifyPriceChange(double price);
public abstract void registerStockExchangeCenter(ObserverStockExchangeCenter oc);
}
abstract class ObserverStockExchangeCenter {
protected Map<StockType, Double> ownedStock;
public ObserverStockExchangeCenter() {
this.ownedStock = new HashMap<>();
}
public void buyStock(ObservableStock s) {
ownedStock.put(s.getName(), 0.0);
}
//assume we won't change values in the map
public Map<StockType, Double> getOwnedStock() {
return ownedStock;
}
public abstract void observe(ObservableStock o);
public abstract void notifyChange(StockType type, double price);
}
enum StockType {
Amazon,
Google,
}
class ObservableStockImpl extends ObservableStock {
private ObserverStockExchangeCenter exchangeCenter;
public final StockType stockType;
public ObservableStockImpl(StockType name ) {
this.stockType = name;
}
public void notifyPriceChange(double price) {
this.exchangeCenter.getOwnedStock().put(stockType, price);
this.exchangeCenter.notifyChange(stockType, price);
}
public void registerStockExchangeCenter(ObserverStockExchangeCenter oc) {
this.exchangeCenter = oc;
}
public StockType getStockType() {
return stockType;
}
}
class ObserverStockExchangeCenterImpl extends ObserverStockExchangeCenter {
private final List<ObservableStockImpl> observableStocks;
public ObserverStockExchangeCenterImpl() {
super();
observableStocks = new ArrayList<>();
}
public void notifyChange(StockType type, double price) {
for (ObservableStockImpl os : observableStocks) {
if (os.getStockType().equals(type)) {
os.setPrice(price);
os.notifyPriceChange(price);
}
}
}
public void observe(ObservableStock o) {
observableStocks.add((ObservableStockImpl) o);
}
@Override
public void buyStock(ObservableStock s) {
ObservableStockImpl stock = (ObservableStockImpl) s;
ownedStock.put(stock.getStockType(), 0.0);
}
}
Answered By - gtiwari333
Answer Checked By - Senaida (JavaFixing Volunteer)