Objects Extended Example General idea Simulate model the
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, Grocery. Item – 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 Grocery. Items – how and where? • Here’s “how”: – The Grocery. Items 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 Grocery. Items – 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 Grocery. Store
The main method, I • What does our main method need to do? – – Create a Grocery. Store Create a Clerk for the store Create a Customer who knows about the store Tell the Customer to “shop” class Grocery. Store { public static void main(String args[]) { Grocery. Store store = new Grocery. Store(); 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 Grocery. Store { public static void main(String args[]) { Grocery. Store store = new Grocery. Store(); 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 1. class Customer { 1. public void shop(Grocery. Store store) { 2. select. Groceries(store); // because the store // holds the groceries 3. check. Out(? ? ? ); // who or what do we pay? } 4. // other stuff. . . 2. }
check. Out(? ? ? ) • Obviously, the Customer should pay the Clerk – But how does the Customer know about the Clerk? • The Customer knows about (can reference) the Grocery. Store • The Clerk knows about the Grocery. Store • Neither the Grocery. Store 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 Grocery. Store know about the Clerk? – This makes sense to me • However, the Clerk still needs to know about the Grocery. Store
The main method, III class Grocery. Store { public static void main(String args[]) { Grocery. Store store = new Grocery. Store(); 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 Grocery. Store • The Grocery. Store knows about the Clerk • Hence, the Customer can ask the Grocery. Store about the Clerk class Customer { public void shop(Grocery. Store store) { select. Groceries(store); check. Out(store); // later we'll ask store for clerk } // other stuff. . . }
The story so far. . . • class Grocery. Store { Grocery. Store() {. . . } // Constructor public static void main(String args[]) {. . . } public void hire(Clerk clerk) {. . . } public Clerk get. Clerk() {. . . } } • class Customer { public void shop(Grocery. Store store) {. . . } public void select. Groceries(Grocery. Store store) {. . . } check. Out(Grocery. Store store) {. . . } } • We haven’t yet done much with either Clerk or Grocery. Item
Hiring a clerk • There’s just one Clerk, whom we hired like this: Grocery. Store store = new Grocery. Store(); 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 Grocery. Store { Clerk my. Clerk; public void hire(Clerk clerk) { my. Clerk = clerk; clerk. take. Position(this); // "this" = this store } }
Being hired class Clerk { Grocery. Store my. Store; public void take. Position(Grocery. Store store) { my. Store = store; } } • Does the Clerk really need to know about the Store? – Yes, because only the Store knows about the Grocery. Items – The Clerk will need to find out about the Grocery. Items in order to check out the Customer
Getting a Clerk • This is trivial, so let’s just do it right now: • class Store { Clerk my. Clerk; . . . public Clerk get. Clerk() { return my. Clerk; }. . . }
Stocking the Store • Next, construct a Store containing an array of Grocery. Items (along with how many of each) // instance variables public int KINDS_OF_ITEMS = 4; public Grocery. Item[ ] item = new Grocery. Item[KINDS_OF_ITEMS]; public int[ ] item. Count = new int[KINDS_OF_ITEMS]; // constructor Grocery. Store() { item[0] = new Grocery. Item("milk", 2. 12); item[1] = new Grocery. Item("butter", 2. 50); item[2] = new Grocery. Item("eggs", 0. 89); item[3] = new Grocery. Item("bread", 1. 59); for (int i = 0; i < KINDS_OF_ITEMS; i++) { item. Count[i] = 50; // the store has lots of everything } }
The Customer selects groceries Grocery. Item[ ] my. Shopping. Basket = new Grocery. Item[20]; Random random = new Random(); public void select. Groceries(Grocery. Store store) { int items. In. My. Basket = 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. next. Int(2) == 1) { my. Shopping. Basket[items. In. My. Basket] = store. item[i]; store. item. Count[i] = store. item. Count[i] - 1; items. In. My. Basket = items. In. My. Basket + 1; } }
The Customer checks out void check. Out(Grocery. Store store) { Clerk clerk = store. get. Clerk(); double total = clerk. ring. Up(my. Shopping. Basket); my. Money = my. Money - total; clerk. pay(total); } • I used a variable my. Money--I have to remember to add that as an instance variable of Customer
The Clerk does his (or her) job public double ring. Up(Grocery. Item[ ] item) { double total = 0; int item. Number = 0; while (item[item. Number] != null) { total = total + item[item. Number]. price; item. Number = item. Number + 1; } return total; } public void pay(double amount) { my. Store. money = my. Store. money + amount; } Remember to add a variable money to Grocery. Store!
The Grocery. Item • The Grocery. Item doesn’t do a lot. . . class Grocery. Item { public String name; public double price; Grocery. Item(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
- Slides: 24