To raise yet another interesting requirements and design problem: How do we handle the case of multiple, conflicting pricing policies? For example, suppose a store has the following policies in effect today (Monday):
Suppose a senior who is also a preferred customer buys 1 case of Darjeeling tea, and $600 of veggieburgers (clearly an enthusiastic vegetarian who loves chai). What pricing policy should be applied?
To clarify: There are now pricing strategies that attach to the sale by virtue of three factors:
Another point of clarification: Three of the four example policies are really just "percentage discount" strategies, which simplifies our view of the problem.
Part of the answer to this problem requires defining the store's conflict resolution strategy. Usually, a store applies the "best for the customer" (lowest price) conflict resolution strategy, but this is not required, and it could change. For example, during a difficult financial period, the store may have to use a "highest price" conflict resolution strategy.
The first point to note is that there can exist multiple co - existing strategies, that is, one sale may have several pricing strategies. Another point to note is that a pricing strategy can be related to the type of customer (for example, a senior). This has creation design implications: The customer type must be known by the StrategyFactory at the time of creation of a pricing strategy for the customer.
Similarly, a pricing strategy can be related to the type of product being bought (for example, Darjeeling tea). This likewise has creation design implications: The ProductDescription must be known by the StrategyFactory at the time of creation of a pricing strategy influenced by the product.
Is there a way to change the design so that the Sale object does not know if it is dealing with one or many pricing strategies, and also offer a design for the conflict resolution? Yes, with the Composite pattern.
For example, a new class called CompositeBestForCustomerPricingStrategy (well, at least it's descriptive) can implement the ISalesPricingStrategy and itself contain other ISalesPricingStrategy objects. Figure explains the design idea in detail.
Observe that in this design, the composite classes such as CompositeBest - For
CustomerPricingStrategy inherit an attribute pricingStrategies that contains a list of more ISalePricingStrategy objects. This is a signature feature of a composite object: The outer composite object contains a list of inner objects, and both the outer and inner objects implement the same interface. That is, the composite class itself implements the ISalePricingStrategy interface.
Thus, we can attach either a composite CompositeBestForCustomerPricingStrategy object (which contains other strategies inside of it) or an atomic PercentDiscountPricingStrategy object to the Sale object, and the Sale does not know or care if its pricing strategy is an atomic or composite strategy - it looks the same to the Sale object. It is just another object that implements the ISalePricingStrategy interface and understands the getTotal message.
Figure 26.14 The Composite pattern
Figure 26.15 Collaboration with a Composite
UML - In Figure, please note a way to indicate objects that implement an interface, when we don't care to specify the exact implementation class.
To clarify with some sample code in Java, the CompositePricingStrategy and one of its subclasses are defined as follows://superclass so all subclasses can inherit a List ofstrategies
Figure 26.16 Abstract superclasses, abstract methods, and inheritance in theUML
Creating Multiple SalePricirigStrategies
With the Composite pattern, we have made a group of multiple (and conflic pricing strategies look to the Sale object like a single pricing strategy. The opposite object that contains the group also implements the ISalePricingStratinterface. The more challenging (and interesting) part of this design problem When do we create these strategies?
A desirable design will start by creating a Composite that contains the present moment's store discount policy (which could be set to 0% discount if none is active), such as some PercentageDiscountPricingStrategy. Then, if at a later step in the scenario, another pricing strategy is discovered to also apply (such as senior discount), it will be easy to add it to the composite, using the inherited CompositePricingStrategy. add method.
There are three points in the scenario where pricing strategies may be added to the composite:
The design of the first case is shown in Figure. As in the original design discussed earlier, the strategy class name to instantiate could be read as a system. property, and a percentage value could be read from an external data store.
Figure 26.17 Creating a composite strategy
For the second case of a customer type discount, first recall the use case extension which previously recognized this requirement:
Use Case UC1: Process Sale
Extensions (or Alternative Flows):
Customer says they are eligible for a discount (e.g., employee, preferred customer)
This indicates a new system operation on the POS system, in addition to make - NewSale, enterltem, endSale, and makePayment. We will call this fifth system operation enterCustomerForDiscount; it may optionally occur after the endSaleoperation. It implies that some form of customer identification will have to come in through the user interface, the customerlD. Perhaps it can be captured from a card reader, or via the keyboard.
The design of the second case is shown in Figures. Not surprisingly, the factory object is responsible for the creation of the additional pricing strategy.
It may make another PercentageDiscountPricingStrategy that represents, for example, a senior discount. But as with the original creation design, the choice of class will be read in as a system property, as will the specific percentage for the customer type, to provide Protected Variations with respect to changing the class or values. Note that by virtue of the Composite pattern, the Sale may have two or three conflicting pricing strategies attached to it. but it continues to look like a single strategy to the Saleobject.
Figure 26.18 Creating the pricing strategy for a customer discount, part 1
UML - Figures show an important UML 2 idea in interaction diagrams: Using the ref and sd frame to relate diagrams.
Considering GRASP and Other Principles in the Design
To review thinking in terms of some basic GRASP patterns: For this second case, why not have the Register send a message to the PricingStrategyFactory, to create this new pricing strategy and then pass it to the Sale?One reason is to support Low Coupling. ThekSaZe is already coupled to the factory; by making the Register also collaborate with it, the coupling in the design would increase. Furthermore, the Sale is the Information Expert that knows its current pricing strategy (which is going to be modified); so by Expert, it is also justified to delegate to the Sale.
Figure 26.19 Creating the pricing strategy for a customer discount, part 2
Observe in the design that customerlD is transformed into a Customer object via the Register asking the Store for a Customer, given an ID. First, it is justifiable to give the getCustomer responsibility to the Store; by Information Expert and the goal of low representational gap, the Store can know all the Customers. And the Register asks the Store, because the Register already has attribute visibility to the Store (from earlier design work); if the Sale had to ask the Store, the Sale would need a reference to the Store, increasing the coupling beyond its current levels, and therefore not supporting Low Coupling.
IDs to Objects
Second, why transformA the customerlD(an "ID" - perhaps a number) into a Customer object? This is a common practice in object design - to transform keys and IDs for things into true objects. This transformation often takes place shortly after an ID or key enters the domain layer of the Design Model from the UI layer. It doesn't have a pattern name, but it could be a candidate for a pattern because it is such a common idiom among experienced object designers - perhaps IDs to Objects.
Why bother? Having a true Customer object that encapsulates a set of information about the customer, and which can have behavior (related to Information Expert, for example), frequently becomes beneficial and flexible as the design grows, even if the designer does not originally perceive a need for a true object and thought instead that a plain number or ID would be sufficient. Note that in the earlier design, the transformation of the itemID into a ProductDescription object is another example of this IDs to Objects pattern.
Pass Aggregate Object as Parameter
Finally, note that in the addCustomerPricingStrategy (s:Sale) message we pass a Sale to the factory, and then the factory turns around and asks for the Customer and PricingStrategy from the Sale.
Why not just extract these two objects from the Sale, and instead pass in the Customer and PricingStrategy to the factory? The answer is another common object design idiom: Avoid extracting child objects out of parent or aggregate objects, and then passing around the child objects. Rather, pass around the aggregate object that contains child objects.
Following this principle increases flexibility, because then the factory can collaborate with the entire Sale in ways we may not have previously anticipated as necessary (which is very common), and as a corollary, it reduces the need to anticipate what the factory object needs; the designer just passes as a parameter the entire Sale, without knowing what more particular objects the factors - may need. Although this idiom does not have a name, it is related to Low Coupling and Protected Variations. Perhaps it could be called the Pass Aggregate Object as Parameter pattern.
Composite is often used with the Strategy and Command patterns. Composite is based on Polymorphism and provides Protected Variations to a client so that it is not impacted if its related objects are atomic or composite.
UML Related Interview Questions
|Adv Java Interview Questions||Java collections framework Interview Questions|
|Design Patterns Interview Questions||Rational robot Interview Questions|
|Web semantic Interview Questions||Spring MVC Framework Interview Questions|
|Advanced C++ Interview Questions||Advanced jQuery Interview Questions|
|XML DOM Interview Questions||Object Oriented Analysis and Design Interview Questions|
Object-oriented Analysis And Design
Iterative, Evolutionary, And Agile
Inception Is Not The Requirements Phase
Iteration 1 Basics
System 'sequence Diagrams
Requirements To Design-iteratively
Logical Architecture And Uml Package Diagrams
On To Object Design
Uml Interaction Diagrams
Uml Class Diagrams
Grasp: Designing Objects With Responsibilities
Object Design Examples With Grasp
Designing For Visibility
Mapping Designs To Code
Test - Driven Development And Refactoring
Uml Tools And Uml As Blueprint
Iteration 2 - More Patterns
Quick Analysis Update
Grasp: More Objects With Responsibilities
Applying Gof Design Patterns
Iteration 3 Intermediate Topics
Uml Activity Diagrams And Modeling
Uml State Machine Diagrams And Modeling
Relating Use Cases
Domain Model Refinement
More Ssds And Contracts
Logical Architecture Refinement
More Object Design With Gof Patterns
Designing A Persistence Framework With Patterns
Uml Deployment And Component Diagrams
Documenting Architecture: Uml & The N+1 View Model
More On Iterative Development And Agile Project Management
All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd
Wisdomjobs.com is one of the best job search sites in India.