Object Example (GroceryStore)

Download Report

Transcript Object Example (GroceryStore)

Objects: Extended Example
General idea
• Simulate (model) the following situation:
– A customer walks into a grocery store, picks up a few
items, pays for them, and leaves
• Let’s write a program to do this
– Limitations:
• As yet, we have no way of interacting with (talking to) the
program, so it will just have to run by itself
– This makes the program kind of boring
– We can include some randomness to make it slightly more
interesting
• We want to keep it simple
– We’ll avoid any problems; for example, we’ll assume the
customer has enough money
Choosing objects
• What objects do we need?
– The obvious objects are:
•
•
•
•
A customer
A store
Grocery items of various sorts
A checkout clerk
– Should we have subclasses of grocery items (milk,
eggs, etc.)?
• My conclusion: No, because these items don’t have different
behaviors
• In fact, they may not have any behaviors at all!
Choosing superclasses
• Our classes are (to give them names): Customer,
Store, Clerk, GroceryItem
– There is no obvious reason for any of these to be a
superclass (or subclass) of any of the others
– I don’t know of any built-in Java classes that provide
any features we need
• Should we make a class Person and use it as a
superclass of Customer and Clerk?
– At the moment, I don’t see any reason to do this
– We can always do it later, if we find some data or
actions that Customer and Clerk should both have
Getting started, I
• We need to create a Customer, a Clerk, a Store,
and some GroceryItems – how and where?
• Here’s “how”:
– The GroceryItems should be in the Store, and initially
only the Store needs to know about them, so we will let
the Store create those
– The Customer and the Clerk both need to know about
the Store (but the Store kind of just sits there)
• Hence, we probably should create the Store first
• This is because, when we create the Clerk and the Customer,
we want to create them with knowledge of the Store
Getting started, II
• We need to create a Customer, a Clerk, a Store,
and some GroceryItems – how and where?
• Here’s “where”:
– We could create a separate class to control all this, but
that’s kind of pointless
– The Store is the central idea of this program, so let’s
put a main method in the Store to kick things off
– That means our main class will be named Store, but I
don’t like that—there are other things we “store” on a
computer
– I’ll rename this class to be GroceryStore
The main method, I
• What does our main method need to do?
–
–
–
–
Create a GroceryStore
Create a Clerk for the store
Create a Customer who knows about the store
Tell the Customer to “shop”
class GroceryStore {
public static void main(String args[]) {
GroceryStore store = new GroceryStore();
Clerk clerk = new Clerk(store);
Customer customer = new Customer(store);
customer.shop(); // This could be better...
}
// other stuff...
}
The main method, II
• According to our code so far, the customer only
shops in this one store
– This is adequate for our program, but it’s very
restrictive and it’s trivial to fix
• class GroceryStore {
public static void main(String args[]) {
GroceryStore store = new GroceryStore();
Clerk clerk = new Clerk(store);
Customer customer = new Customer( );
customer.shop(store);
}
// other stuff...
}
The Customer, I
• The Customer needs to shop
– This includes selecting groceries and paying for them
class Customer {
public void shop(GroceryStore store) {
selectGroceries(store); // because the store
// holds the groceries
checkOut(???); // who or what do we pay?
}
// other stuff...
}
checkOut(???)
• Obviously, the Customer should pay the Clerk
– But how does the Customer know about the Clerk?
• The Customer knows about (can reference) the GroceryStore
• The Clerk knows about the GroceryStore
• Neither the GroceryStore nor the Customer knows about the
Clerk
• We can’t get there from here!
– How do we fix this?
• Should the Customer know about the Clerk?
– I don’t know any clerks personally, so why should my
Customer object?
• Should the GroceryStore know about the Clerk?
– This makes sense to me
• However, the Clerk still needs to know about the GroceryStore
The main method, III
class GroceryStore {
public static void main(String args[]) {
GroceryStore store = new GroceryStore();
Clerk clerk = new Clerk(store);
store.hire(clerk);
Customer customer = new Customer();
customer.shop(store);
}
// other stuff...
We can do this when
}
we hire the Clerk
The Customer, II
• The Customer knows about the GroceryStore
• The GroceryStore knows about the Clerk
• Hence, the Customer can ask the GroceryStore
about the Clerk
class Customer {
public void shop(GroceryStore store) {
selectGroceries(store);
checkOut(store); // later we'll ask store for clerk
}
// other stuff...
}
The story so far...
• class GroceryStore {
GroceryStore() {...} // Constructor
public static void main(String args[]) {...}
public void hire(Clerk clerk) {...}
public Clerk getClerk() {...}
}
• class Customer {
public void shop(GroceryStore store) {...}
public void selectGroceries(GroceryStore store) {...}
checkOut(GroceryStore store) {...}
}
• We haven’t yet done much with either Clerk or GroceryItem
Hiring a clerk
• There’s just one Clerk, whom we hired like this:
GroceryStore store = new GroceryStore();
Clerk clerk = new Clerk();
store.hire(clerk);
• So we need to write the hire method
– Also, don’t forget the store and clerk need to know about each other
class GroceryStore {
Clerk myClerk;
public void hire(Clerk clerk) {
myClerk = clerk;
clerk.takePosition(this); // "this" = this store
}
}
Being hired
class Clerk {
GroceryStore myStore;
public void takePosition(GroceryStore store) {
myStore = store;
}
}
• Does the Clerk really need to know about the Store?
– Yes, because only the Store knows about the GroceryItems
– The Clerk will need to find out about the GroceryItems in order to
check out the Customer
Getting a Clerk
• This is trivial, so let’s just do it right now:
• class Store {
Clerk myClerk;
...
public Clerk getClerk() {
return myClerk;
}
...
}
Stocking the Store
• Next, construct a Store containing an array of
GroceryItems (along with how many of each)
// instance variables
public int KINDS_OF_ITEMS = 4;
public GroceryItem[ ] item = new GroceryItem[KINDS_OF_ITEMS];
public int[ ] itemCount = new int[KINDS_OF_ITEMS];
// constructor
GroceryStore() {
item[0] = new GroceryItem("milk", 2.12);
item[1] = new GroceryItem("butter", 2.50);
item[2] = new GroceryItem("eggs", 0.89);
item[3] = new GroceryItem("bread", 1.59);
for (int i = 0; i < KINDS_OF_ITEMS; i++) {
itemCount[i] = 50; // the store has lots of everything
}
}
The Customer selects groceries
GroceryItem[ ] myShoppingBasket = new GroceryItem[20];
Random random = new Random();
public void selectGroceries(GroceryStore store) {
int itemsInMyBasket = 0;
for (int i = 0; i < store.KINDS_OF_ITEMS; i++) { // for each kind of item
for (int j = 0; j < 3; j++) {
// choose up to 3 of it
if (random.nextInt(2) == 1) {
myShoppingBasket[itemsInMyBasket] = store.item[i];
store.itemCount[i] = store.itemCount[i] - 1;
itemsInMyBasket = itemsInMyBasket + 1;
}
}
}
}
The Customer checks out
void checkOut(GroceryStore store) {
Clerk clerk = store.getClerk();
double total = clerk.ringUp(myShoppingBasket);
myMoney = myMoney - total;
clerk.pay(total);
}
• I used a variable myMoney--I have to remember to add
that as an instance variable of Customer
The Clerk does his (or her) job
public double ringUp(GroceryItem[ ] item) {
double total = 0;
int itemNumber = 0;
while (item[itemNumber] != null) {
total = total + item[itemNumber].price;
itemNumber = itemNumber + 1;
}
return total;
}
public void pay(double amount) {
myStore.money = myStore.money + amount;
}
Remember to add a variable money to GroceryStore!
The GroceryItem
• The GroceryItem doesn’t do a lot...
class GroceryItem {
public String name;
public double price;
GroceryItem(String name, double price) {
this.name = name;
this.price = price;
}
}
What’s left?
• The program is complete, except for one minor
detail:
– When it runs, we don’t know what it does
– We never printed anything
• Easy solution:
– As the Clerk rings things up, print them out
– We could also have the Customer print things out as he
(or she) picks them up
A little “philosophy”
• As written, the Store doesn’t do anything--it just
sits there and lets people manipulate it
– This is pretty much true to life
– But is it a good idea for a program?
• Suppose the Customer takes more of an item than
the Store has (leaving it with a negative amount)
– We could make the Customer responsible
– But maybe the Clerk also manipulates the amount
(stocks the shelves)
– Now the responsibility is split into two different places
– Suddenly, this is twice as hard to maintain
– Conclusion: the Store should be responsible for its own
state, whether or not this is like “real life”
The End