Using Observable/Observer with two different double variables? - java

I have a class that monitors the stock market. It holds 2 values (doubles) the daily high and the daily low. I want to monitor these variables from another class and take action if either changes. (i.e. change a limit order)
So, I have a class LiveOrderBook extends Observable and two methods inside that update the price:
public void setDailyLow(double price){
low = price;
setChanged();
notifyObservers(low);
}
public void setDailyHigh(double price){
high = price;
setChanged();
notifyObservers(high);
}
I need to observe these price variables so I made a class PriceObserver implements Observer. My plan is to create PriceObserver objects inside my Bid class that changes stock market bids.
My PriceObserver class
private double low;
private double high;
public PriceObserver(){
low = 0;
high = 0;
}
public void update(Observable arg0, Object arg1) {
// TODO Auto-generated method stub
}
How do I now specify which double should be updated? I can't check if arg0 == the variable name from the other class, so how is this done?

An easy (and useful) approach is to first create different event classes that can get dispatched:
public class LowPriceChangedEvent {
private double price;
// Constructor and getter up to you.
}
public class HighPriceChangedEvent {
private double price;
// Constructor and getter up to you.
}
Now you can dispatch these events in your LiveOrderBook class:
public void setDailyLow(double price){
low = price;
setChanged();
notifyObservers(new LowPriceChangedEvent(low));
}
public void setDailyHigh(double price){
high = price;
setChanged();
notifyObservers(new HighPriceChangedEvent(low));
}
Your PriceObserver now easily can distinguish the events by doing a simple instanceOf check:
public class PriceObserver implements Observer {
#Override
public void update(Observable o, Object arg) {
if (arg instanceOf LowPriceChangedEvent) {
...
} else if (arg instanceOf HighPriceChangedEvent) {
...
} else {
...
}
}
}

Your arg1 is an Object. I would suggest calling your notifyObservers method with a double[] (all arrays are castable to Object).
i.e.
notifyObservers(new double[] {low, high});

Related

Using strategy pattern along with Dependency injection

I'm going through Strategy pattern listed out in https://en.wikipedia.org/wiki/Strategy_pattern and trying to understand how this would work when you want to use Dependency injection as well and make it easy for unit testing.
So the interface is:
interface BillingStrategy {
// Use a price in cents to avoid floating point round-off error
int getActPrice(int rawPrice);
}
There are two implementations:
#Component
NormalHours implements BillingStrategy {
public int getActPrice(int rawPrice) {
return rawPrice;
}
}
#Component
HappyHours implements BillingStrategy {
public int getActPrice(int rawPrice) {
return rawPrice/2;
}
}
Now there is a customer object for whom I want to keep track of how the total price:
class Customer {
private final List<Integer> drinks = new ArrayList<>();
private BillingStrategy strategy;
public Customer(BillingStrategy strategy) {
this.strategy = strategy;
}
public void add(int price, int quantity) {
this.drinks.add(this.strategy.getActPrice(price*quantity));
}
// Payment of bill
public int getBill() {
int sum = this.drinks.stream().mapToInt(v -> v).sum();
this.drinks.clear();
return sum;
}
// Set Strategy
public void setStrategy(BillingStrategy strategy) {
this.strategy = strategy;
}
}
Now say I've a file which I've which has information about purchases made during each hour of the day, and I need to compute the final bill for the customer.
#Component
public class Calculator {
public int calculate(File file) {
//pseudo code here
Customer customer = new Customer();
for(line in file) {
//parse price, strategy and quantity from line
customer.setStrategy(strategy);
customer.add(price, quantity);
}
return customer.getBill();
}
}
Obviously this doesn't work great for unit testing as a new object is created within the method and by using just regular Mockito it's going to be hard to mock the values returned for the strategies in Calculator class. Is there a different way to model the Customer & Calculator class to ensure ease of testing and use DI as much as possible?
I know one way is let the caller of Calculator pass in the object Customer, but however with the way the wiki has explained this particular Customer class we cannot make it as a Singleton and the same problem will exist.
Given strategy isn't related to the Customer itself and placing it inside Customer is DI violation. Instead just pass strategy as method argument
class Customer {
private final List<Integer> drinks = new ArrayList<>();
public void add(BillingStrategy strategy, int price, int quantity) {
drinks.add(strategy.getActPrice(price * quantity));
}
// Payment of bill
public int getBill() {
int sum = drinks.stream().mapToInt(v -> v).sum();
drinks.clear();
return sum;
}
}
#Component
public class Calculator {
public int calculate(Customer customer, File file) {
//pseudo code here
for(line in file) {
//parse price, strategy and quantity from line
customer.add(strategy, price, quantity);
}
return customer.getBill();
}
}

Calling methods with objects trouble

So, I need to do this for part of my homework :
Create a method in the Customer class called hasMoreMoneyThan(Customer c)
which returns true if the customer calling the method has more money than the
customer c, otherwise it should return false.
I am looking to be pointed in the right direction for the line that says "the customer calling the method"
This is very confusing to me and doesn't make sense, this my Customer is a class.
Here is the necessary code :
public class Customer
{
private String name;
private int age;
private float money;
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public Customer(String n, int a, float m)
{
name = n;
age = a;
money = m;
}
I started writing the method:
public boolean hasMoreMoneyThan(Customer c)
{
}
But am not sure how to call that with my Customer object (which I think the question is asking.
Other relevant code :
public class StoreTestProgram {
public static void main(String args[]) {
Customer[] result;
Store walmart;
walmart = new Store("Walmart off Innes");
walmart.addCustomer(new Customer("Amie", 14, 100));
}
}
When a method is called on an object, the objects variables are in the current scope. In this case, the 'customer calling the method' is the object that the method is being called on (object being an instance of the class).
So, if boolean hasMoreMoneyThan(Customer c) is being called on Customer a, then you should think of it as asking Customer a has more money than Customer c?.
You can use the this keyword to refer to the current object (to help the reader differentiate from Customer c).
So, in your hasMoreMoneyThan method, you can compare this.money with c.money.
And to call this method, you need a reference to the current customer and the customer you want to compare with. You could do something like:
Customer currentCustomer = new Customer(...
Customer customerToCompareWith = new Customer(...
if (currentCustomer.hasMoreMoneyThan(customerToCompareWith)) {
// do something
}
Edit Let's try a different example. Let's say you want a method to know whether a customer is older than another customer. That code might look like:
public boolean isOlderThan(Customer c) {
return this.age > c.age;
}
And to call the method:
if (currentCustomer.isOlderThan(customerToCompareWith)) {
// the current customer is older
} else {
// the current customer is not older
}
this is how you reference an object from methods that are members of an object. this.money ><=? c.money
if in your constructor you you used public Customer(String name, int age, float money) you would use this.name= name instead of name= n to clear up ambiguity.

Storing and calling specific class methods in/from an array

I've been reading and googling for hours on how I can call
public class Fee {
int id;
String name;
double amount;
FeeCategory feeCategory; // miscellaneous, other, tuition, etc
GradeLevel gradeLevel;
SchoolYear schoolYear;
String description;
boolean isActive;
public boolean isIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
public FeeCategory getFeeCategory() {
return feeCategory;
}
public void setFeeCategory(FeeCategory feeCategory) {
this.feeCategory = feeCategory;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public GradeLevel getGradeLevel() {
return gradeLevel;
}
public void setGradeLevel(GradeLevel gradeLevel) {
this.gradeLevel = gradeLevel;
}
public SchoolYear getSchoolYear() {
return schoolYear;
}
public void setSchoolYear(SchoolYear schoolYear) {
this.schoolYear = schoolYear;
}
I have a number of different getter methods along with its setter methods.
I need to be able to call the method to fill the cells of a JTable with specific values returned by corresponding getter method.
So what I did was create a DefaultTableCellRenderer
public class JTableRenderer extends DefaultTableCellRenderer{
#Override
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int col)
{
Component cellComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
if(row%2 == 0){
cellComponent.setBackground(Color.YELLOW);
}
else{
cellComponent.setBackground(Color.CYAN);
}
for(int i=0; i<table.getRowCount(); i++){
for(int j=0; j<table.getColumnCount(); j++){
if(table.getValueAt(i, j) instanceof Fee){
Fee fee = (Fee)table.getValueAt(i, j);
table.setValue(fee.getId(),i,j);
}
}
}
return cellComponent;
}
}
The problem is with the for loop which I plan to use to set specific values for certain cells.
As you can see, it filled all the cells with just the id because I can't think of a way to iterate through getId(),getName(),getAmount(),getDescription().
Is it possible to put all 4 methods in an array maybe something like
Methods[] myMethods = {getId(),getName(),getAmount(),getDescription()};
then,
for(int i=0; i<table.getRowCount(); i++){
for(int j=0; j<table.getColumnCount(); j++){
if(table.getValueAt(i, j) instanceof Fee){
Fee fee = (Fee)table.getValueAt(i, j);
table.setValue(fee.myMethod[j],i,j);
}
}
}
I want to call just the 4 getter methods but not all of them.
Any solution or suggestion?
You are going to need some sort of switching logic to handle the mapping of index to getter method. For me, the neatest way is to use Java 8 lambda functions, something like the example below. As you can see, this adds a getValue(int index) method to the Fee class which does what you want. The mapping is handled by a Map created in the static initialisation.
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class Fee {
private String name;
private int fee;
private static Map<Integer, Function<Fee, Object>> getterIndex = new HashMap<>();
static {
getterIndex.put(0, Fee::getName);
getterIndex.put(1, Fee::getFee);
}
public String getName() {
return name;
}
public Fee setName(String name) {
this.name = name;
return this;
}
public int getFee() {
return fee;
}
public Fee setFee(int fee) {
this.fee = fee;
return this;
}
public Object getValue(int index) {
return getterIndex.get(index).apply(this);
}
public static void main(String[] args) {
Fee fee = new Fee().setName("Barry").setFee(1000);
System.out.println("name: " + fee.getValue(0));
System.out.println("fee : " + fee.getValue(1));
}
}
In order to dynamically call methods like that, you'll need to use reflection and possibly introspection.
Reflection is when you programmatically use the structures of your program itself, such as Class instances, the methods they define. If you take a look at the Java Class class, you'll find it has methods for accessing its constructors, fields, methods and more.
Introspection is the ability to use properties of some object at run-time. Classes that conform to the JavaBeans specification allow introspection, which offers some abstraction that's easier to use than pure reflection. The Introspector class in package java.beans allows you to obtain bean info for a class. From there, the "properties" of that class can be used. A property could be a field with a getter and/or setter, or a getter/setter not backed by a field (that may simply operate on logic). It allows for more than that, such as registering a listener with a property on an instance so that if the property is changed through a setter, the listener is called. This is useful for a model-view-controller approach, where changes to some instance may require update events being fired on the view. For example, if some part of your code changes properties of objects that are represented as rows in your table, outside of the GUI, the listener could be used to update the corresponding cell.
If you want to use an array, you'll have to populate it with Method instances. These would be the read methods (and possibly a separate array with write methods) for the corresponding PropertyDescriptors you get via the introspection. Such a Method can then be invoked on an object, provided the access rules allow it. It might actually be better to use a Map, which maps names to the Method, so the actual order doesn't matter. This would make it easier to refactor your user interface later. You may also want some way of mapping the actual column names to the property names, but if you set specific rules regarding naming and stick to them, you could derive the property names from the column names, or reverse things and show a column for each property automatically.
EDIT: Maybe interesting to know why you need to do these things in such a round-about way. Java does not have first class methods. This means that methods cannot be passed around as arguments or treated as any other piece of data, the way you could in JavaScript or Scala. So reflection is needed to obtain and invoke methods indirectly. Java 8 introduced some functional programming concepts with lambdas, but they are a form of single-method interface in disguise. Furthermore, Java is not a dynamic language such as Ruby or Python, it is a statically compiled language. So some things that are simple (but also easy to break) in other languages require reflection in Java. If you come from a non-Java background, the way you need to do some things may feel cumbersome.
Add to Fee class:
public Object myMethod(int j) {
switch (j) {
case 0:
return this.getId();
case 1:
return this.getName();
case 2:
return this.getAmount();
case 3:
return this.getDescription();
default:
throw new IllegalArgumentException();
}
}
You should have a list of Fee records:
List<Fee> feeData=new ArrayList<Fee>();
Then call:
for(int i=0; i<feeData.size(); i++){
if(feeData.get(i) instanceof Fee){
for(int j=0; j<table.getColumnCount(); j++){
Fee fee = (Fee)feeData.get(i);
table.setValueAt(fee.myMethod(j),i,j);
}
}
}

Need explanation of java Class collaboration/aggregation

I'm working on an assignment where I need to make 3 classes for a car simulator. One for the fuel and one for the mileage. "The mileage class should be able to work with a FuelGauge object. It should decrease the FuelGauge object's current amount of fuel by 1 gallon for every 24 miles traveled. (The car's fuel economy is 24 miles per gallon)." I'm just really struggling on understanding how to properly link the classes together so that they can do what is necessary.
A good explanation from someone would be greatly appreciated.
I hope I understand your problem correctly.
Simple answer is that FuelGauge class will have attribute amount, which will be accessible through simple setter/getter.
public class FuelGague {
private double amount;
// Starting amount of fuel
public FuelGague(double amount) {
this.amount = amount;
}
// Not sure if you really need this method for your solution. This is classic setter method.
public void setAmount(double amount) {
this.amount = amount;
}
public double getAmount() {
return amount;
}
// I guess this is what do you actually want to do
public void changeAmount(double difference) {
amount += difference;
}
}
public class Mileage {
private FuelGague fuelGague;
public Mileage(FuelGague fuelGague) {
this.fuelGague = fuelGague;
}
// This will be main method where you can decrease amount for guelGague
public void methodForMileage() {
fuelGague.changeAmount(-1);
}
public FuelGague getFuelGague() {
return fuelGague;
}
public void setFuelGague(FuelGague fuelGague) {
this.fuelGague = fuelGague;
}
public static void main(String[] args)
{
FuelGague fuelGague= new FuelGague(50);
Mileage mil = new Mileage(fuelGague);
}
}
As you can see Mileage class has refference to fuelGague object which is passed in constructor and it can be manipulated by public method of FuelGague class. I added set method for Mileage class so you can even set different FuelGague class object.

Implementation question regarding base classes and derived classes

I have a question regarding the best way to implement this. I'm going to describe my current implementation and how I seem to have painted myself into a corner:
I have an abstract class called Package:
public abstract class Package {
protected String description;
protected String packagingCode;
protected Dimension dimensions;
protected Weight weight;
protected Package() {
this.description = null;
this.packagingCode = null;
this.dimensions = null;
this.weight = null;
}
protected Package(String description, String packagingCode, Dimension dimensions, Weight weight) throws ShippingException {
this.description = description;
this.packagingCode = packagingCode;
this.dimensions = dimensions;
this.weight = weight;
String exceptionMessage = "";
if(!meetsWeightRequirements()) {
exceptionMessage = "This package's weight exceeds limits. ";
}
if(!meetsDimensionalRequirements()) {
exceptionMessage += "This package's dimensions exceed limits.";
}
if(!StringUtils.isEmpty(exceptionMessage)) {
throw new ShippingException(exceptionMessage);
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPackagingCode() {
return packagingCode;
}
public void setPackagingCode(String packagingCode) {
this.packagingCode = packagingCode;
}
public Dimension getPackageDimensions() {
return dimensions;
}
public void setPackageDimensions(Dimension dimensions) throws ShippingException {
this.dimensions = dimensions;
if(!meetsDimensionalRequirements()) {
this.dimensions = null;
throw new ShippingException("This package's dimensions exceed limits.");
}
}
public Weight getPackageWeight() {
return weight;
}
public void setPackageWeight(Weight weight) throws ShippingException {
this.weight = weight;
if(!meetsWeightRequirements()) {
this.weight = null;
throw new ShippingException("This package's weight exceeds limits.");
}
}
public abstract boolean meetsWeightRequirements();
public abstract boolean meetsDimensionalRequirements();
}
Then I have classes that extend this abstract class like so:
public class WeightBasedPackage extends Package {
public boolean meetsWeightRequirements() {
Weight weight = this.getPackageWeight();
boolean meetsRequirements = false;
if(weight != null) {
meetsRequirements = (weight.getWeight() > 0);
}
return meetsRequirements;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
I have another object (ShipRequest) that maintains a List of Packages (List<Package>). I also have a services (eg WeightBasedPackageShipService) that uses this object and can access this list of packages. This implementation has worked fine because the services don't really care what type of package it is. The only difference between the packages is the way they implement the abstract methods.
Now here is where the problem comes in. I created a new class:
public class OrderQuantityPackage extends Package {
int quantity;
public OrderQuantityPackage() {
super();
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getQuantity() {
return this.quantity;
}
public boolean meetsWeightRequirements() {
return true;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
Which has a quantity field. I need to access this field in the service (OrderQuantityPackageShipService). However, since it is of type Package I have to cast it (it seems kinda kludgey).
My question is, how do I implement this in a better fashion (so I don't have to cast) and also ensure type-safety (So that if you are using OrderQuantityPackageShipService, the package must be of type OrderQuantityPackage). I thought about using Generics, but it seems a little to kludgey for what I am trying to do (ShipRequest has a bunch of other attributes and it seemed strange to genericize it based on the type of package).
Thanks.
public abstract class Package {
protected String description; // These shouldn't be private fields instead of protected?
protected String packagingCode; // Nah, I don't think so, otherwise how could I store a value into the Quantity field? =P
protected Dimension dimensions;
protected Weight weight;
protected int quantity;
// Constructors, getters and setters...
public virtual int getQuantity {
throw new NotImplementedException();
}
public virtual int setQuantity(int quantity) {
throw new NotImplementedException();
}
}
public final class OrderQuantityPackage extends Package {
public override int getQuantity {
return super.quantity;
}
public override void setQuantity(int quantity) {
super.quantity = quantity;
}
}
I'm not completely sure about the syntax though, and neither about the NotImplementedException, but I hope you get the idea. So, any Package derived class that needs or require a quantity may do so by overriding the getter and setter of the Quantity property.
No exception should be thrown as of where the Quantity won't be required, it shouldn't get called, so no exception shall be thrown. Furthermore, it testifies that your model only does what it is required when times come.
In addition to it, OrderQuantityShipService shouldn't require a Weight property within the OrderQuantityPackage, and as written by Vivin, one could access the weight anyway.
Otherwise, a simple cast within your service should do it. It is no dirty way to go to use casting. For instance, one must cast the sender object within an event handler to the proper control type he wishes to check for name, state or other property values! The most general class is then passed on to the event, and one must cast... And this, that is not me who said to opt this way, these are software engineers!...
EDIT Vivin, how do one cast from a data type to another in JAVA, is it as in C/C++/C# ?
CastedType variable = (CastedType)TypeCast;
Short Answer: Dependency Inversion
You have a OrderQuantityPackageShipService class that requires certain features from the objects that it processes. So OrderQuantityPackageShipService should be the one specifying those requirements. Typically this is done with an interface. If it is very specific to the service, create the interface nested. ie:
class OrderQuantityPackageShipService {
//...
interface QuantityPackage {
int getQuantity();
// ...
}
}
if it can be used in a consistent manner by other services, define it outside of the OrderQuantityPackageShipService class.
Then have certain packages implement that interface...
Maybe you should create an abstract service and extend it for the different kinds of packages to handle. You could have the handling method be abstract and have each kind of service know what to do with the corresponding package. If you're not to mix types of packages then this might work.
One thing I can think of is why would you need to access the quantity attribute in the class OrderQuantityPackageShipService ? As I look at it you have a getter and setter for each attribute of the class Package. Are these getters and setters really needed ? Having getters/setters for all those attributes doesn't go well with encapsulation.
Can you think of providing public methods in Package class that operate at a higher level and don't expose the internal attributes ? Wouldn't that help ?

Categories