Using strategy pattern along with Dependency injection - java

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();
}
}

Related

Is there a way to efficiently audit statistics attributes of objects in Java?

Say I have a class Person, and I created 10 instances of Person, and each person has several different attributes, such as enum Gender{MALE, FEMALE}, enum Profession{CEO, POLICE, TEACHER}, etc.
And I somehow have to randomly create many persons with random attributes and use a dedicated class to audit the statistics of created persons' attributes.
So, eventually, I need to generate a list of attributes with some statistics accordingly, such as, "FEMALE: [number], POLICE: [number],...".
Currently, I'm planning to add all kinds of the persons' attributes count, as a bunch of new attributes to the audit class, such as, "femaleCount int, policeCount int, ..." then manipulate the counts based on generated persons.
But, I got 10-ish attributes for each person, so I wonder if there is a better way to do this.
Thanks for your reading.
One possible approach is below, but do not say that it's the only one neither the best.
It's only depends of the purpose and your design.Other option maybe it's to store all Persons in a data-structure List and just compute the statistic based on data at a certain time (have also update/delete here)
Version where only add is counting ...
public class Statistic
{
private static Statistic s=null;
public int countPerson;
public int countMale;
public int countFemale;
public static Statistic getInstance()
{
if(s==null)
s = new Statistic(0, 0, 0);
return s;
}
public static Statistic getInstace(int cP,int cM, int cF)
{
if(s==null)
s = new Statistic(cP, cM, cF);
return s;
}
//do whatever init wanted
private Statistic(int cP,int cM, int cF)
{
countPerson = cP;
countMale = cM;
countFemale = cF;
}
public String toString()
{
return "Total="+countPerson+", Male="+countMale+", Female=" + countFemale;
}
}
...
public class Person
{
public int id;
public String name;
public Gender g;
public Profession p;
public enum Gender{MALE, FEMALE};
public enum Profession{CEO, POLICE, TEACHER}
Person(int id,String name, Gender g, Profession p)
{
this.id = id;
this.name = name;
this.g = g;
this.p = p;
Statistic.getInstance().countPerson++;
if(g.equals(Gender.MALE))
{
Statistic.getInstance().countMale++;
}
else
{
Statistic.getInstance().countFemale++;
}
}
}
...
public class TestStat {
public static void main(String[] args)
{
//cPersons,cMale,cFemale - init
Statistic.getInstace(10, 5, 5);
System.out.println(Statistic.getInstance());
new Person(1,"Male",Person.Gender.MALE, Person.Profession.TEACHER);
System.out.println(Statistic.getInstance());
new Person(2,"Female",Person.Gender.FEMALE, Person.Profession.CEO);
System.out.println(Statistic.getInstance());
}
}
Output
//custom start from (10,5,5) based on Singleton Custom Constructor
Total=10, Male=5, Female=5
//start update counters
Total=11, Male=6, Female=5
Total=12, Male=6, Female=6
Thinking twice maybe it's better to keep a List with Persons on Singleton
and make each time a new Computation - from Singleton instead on Person.
About Delete a person which can be translated in "moving from a Company to other" and then it's not to be reflected on Statistic.
Even so, on current you could add a delete method on person which could be reflected with adjust Statistic with minus and Person-Instance with null.
Further, it's up to you to update design as wanted.

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.

Using Observable/Observer with two different double variables?

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});

Is my scenario come under Prototype Design Pattern?

Scenario 1 :
I am generating a report for more department's performance and participation in a institute. When I am display the report in GUI, it can be sort by department performance and participation(No.of student participated).
For this scenario, should i use Prototype Design pattern?
Ex :
public abstract class Report implements Cloneable {
private String id;
protected String type;
public void setId(String id){
id=id;
}
public String getId(){
return id;
}
public String getType(){
return type;
}
abstract void getReportData();
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
public class PerformanceReport extends Report {
public PerformanceReport(){
type = "Performance";
}
#Override
public void getReportData() {
/* Get report data from database and sort based on performance*/
}
}
public class ParticipationReport extends Report {
public ParticipationReport(){
type = "Participation";
}
#Override
public void getReportData() {
/* Get report data from database and sort based on participation*/
}
}
public class ReportCache {
private static Hashtable<String, Report> reportMap = new Hashtable<String, Report>();
public static Report getReport(String reportid) {
Report cachedReport = reportMap.get(reportid);
return (Report) cachedReport.clone();
}
public static void loadCache() {
ParticipationReport participationReport = new ParticipationReport();
participationReport.setId("1");
reportMap.put(report.getId(),report);
PerformanceReport performanceReport = new PerformanceReport();
performancenReport.setId("2");
reportMap.put(report.getId(),report);
}
}
public class PrototypePatternReport {
public static void main(String[] args) {
ReportCache.loadCache();
Report clonedReport = (Report) ReportCache.getReport("1");
System.out.println("Report : " + clonedReport.getType());
Report clonedReport2 = (Report) ReportCache.getReport("2");
System.out.println("Report : " + clonedReport2.getType());
}
}
Is my above concept is correct ? and this concept is relevant to Prototype-pattern?
Scenario 2 :
I am storing quiz detail (questions and options, answers) in a object, while student request for quiz, I should encrypt the answer and give. For encrypted answer i should keep another object to give. I this scenario can i use prototype? After response come from student I should compare the student answer with existing object.
Prototype pattern is often useful when object initialization is expensive or when you explicitly need an object that is a copy of another.
Scenario 1:
In your case, getting report data from database and sorting it is much more expensive than instantiating an object, and each report will consist on its own data (you will not benefit from copying from another object) so I would not consider using a prototype.
Scenario 2:
In this scenario, the key is
For encrypted answer i should keep another object to give
In this case, as you need another object and you need to ensure that the second object is an exact copy of the first, you could use a prototype to create the second object, and then change its properties to ensure that the answers are hidden.

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