The context: We have a software system to operate a marketplace, where buyers and vendors are matched up. The system was developed by accretion, with different parts designed and implemented at different times by different people. The system was then integrated by some students from Harvard; the resulting design works but it is not ideal!
In this market, a vendor offers a lot, which is a fixed quantity of some product, available at a given price. A buyer may purchase the lot as a whole; there is no possibility of subdividing a lot and buying only part of the quantity available.
Each buyer is represented in the system by a software agent, which follows a fixed policy. We support two policies:
Whenever an agent buys a lot, the buyer should be contacted. There are two ways a buyer can be contacted.
Each Vendor is represented by an object which is provided to us, and can't be modified. It expects to call a method offerForSale(vendor, offerId, productCode, quantity, unitPrice) of the unique MarketPlace object; it expects that the MarketPlace will call the method sold(offerId) when this lot is eventually sold. Note that offerId is only meaningful between the MarketPlace and a given Vendor; different Vendors may use the same offerId for a different lot. Also, we do not include any possibility for the vendor to retract an offered lot; the MarketPlace may wait a long time before the Vendor finds that the lot was sold, and the lot remains available until some Buyer seeks to buy it.
By the way, in a multi-threaded system, when an agent finds a lot that it decides to buy, it may not be successful because the lot may have already been sold between the time when the agent sees the lot is available, and the time when the agent indicates its willingness to buy. We do not deal with this in our single-threaded system, although some methods have specs which take this possibility into account.
Here is the design of the system
Marketplace void offerForSale(vendor, offerId, productCode, quantity, unitPrice) // creates a Lot object, // and then informs all buyers, one after another, of the new offer, // using the methods appropriate to the different buyers. // N.B. if a PriceDrivenBuyer accepts the offer immediately, // the vendor's sold method is called. // Once the lot is sold (either to a PriceDrivenBuyer through their // lotOffered method, or by a BargainBuyer calling back the bid method) // other buyers are not told of the offer. Lot[] queryProduct(productCode) //return unsold lots involving productCode void addPriceDrivenBuyer(PriceDrivenBuyer pdb) void removePriceDrivenBuyer(PriceDrivenBuyer pdb) void addBargainBuyer(BargainBuyer bb) // BargainBuyers are not removed boolean bid(Lot) //return true if this is the first bid for this lot, // indicating the bid is successful; in that case, // a side effect will be to call the vendor's sold(offerId) method. Lot an immutable class has fields storing productCode, quantity, unitPrice, vendor, offerId has methods to report on these fields PriceDrivenBuyer PriceDrivenBuyer(productCode, quantity, unitPriceLimit) // constructor void contactDetails(Pager pager) // provide a Pager for contact // this invalidates any previous contact information void contactDetails(String faxnumber) // provide a faxnumber for contact // this invalidates any previous contact information boolean lotOffered(Lot l) // informs agent of a new lot on offer // returns true if agent wants to buy this // N.B. in this case buyer certainly succeeds in purchase BargainBuyer BargainBuyer(int[] productCodes, float threshhold) // constructor void contactDetails(Pager pager) // provide a Pager for contact // this invalidates any previous contact information void contactDetails(String faxnumber) // provide a faxnumber for contact // this invalidates any previous contact information void lotOffered() // informs agent of a new lot on offer; // this triggers agent to query for unsold offers of // each of the products it wants; // if any lots are bargains, they are accepted // by calling MarketPlace's bid method
There are also classes Vendor, FaxSystem, and Pager described above. They are provided externally and must be used as-is.
Some desired extensions: You need to describe how the design above would need to change, to allow the following extra functionality
You should then suggest a better design (based on some of the Patterns presented in class) which will meet the original requirements and also be easy to extend for the added features. Recall that the object representing each Vendor and the one which represents the real-world Pager and FaxSystem are provided from outside, and therefore they can't be modified in your alternative design.
Also, discuss some other extensions that might be wanted, and how the design can accomodate these.