To consider
There are the following types of design:
What if the price of milk goes up? What happens when you add a caramel flavor?
What design principle did we mention earlier violate by creating this maintenance difficulty?P82
- Take out and encapsulate the changed parts, leaving the rest untouched
- Use composition more than inheritance
To consider
Write code for the cost() method of the following class. P83
public class Beverage {
public double cost(a) {
double totalCost = 0.0;
if (hasMilk()) {
totalCost += milkCost;
}
if (hasSoy()) {
totalCost += soyCost;
}
if (hasMocha()) {
totalCost += mochaCost;
}
if (hasWhip()) {
totalCost += whipCost;
}
returntotalCost; }}Copy the code
Concrete class: DarkRoast
public class DarkRoast extends Beverage {
public DarkRoast(a) {
description = "Most Excellent Dark Roast";
}
public double cost(a) {
return baseCost + super.cost(); }}Copy the code
To consider
What requirements or factors will affect the design when it changes? P84
- The change in seasoning price will cause us to change the existing code
- As soon as we have a new seasoning, we need to add a new method and change the cost() method in the superclass
- New drinks may be developed later. For these drinks (e.g., iced Tea), some seasonings may not be appropriate, but in this design, the Tea subclass will inherit methods that are not appropriate, e.g., hasWhip().
- What if the customer wants a double mocha or coffee?
- Condiments vary with the specific drink
- The base price of drinks varies from large to medium size
Design principles
- The open closed principleClasses should be open for extension and closed for modification
P86
- Policy mode, Observer mode, and decorator mode all follow the open and closed principle
P105
- Policy mode, Observer mode, and decorator mode all follow the open and closed principle
Decorator mode
Dynamically attaching responsibility to an object without changing its original code. Decorators provide a more resilient alternative to inheritance when extending functionality.P91
The characteristics of
- Decorator classes and decorated classes have the same supertype
P90
- A decorator class can precede (or follow) the behavior of the delegated decorator class by adding its own behavior to achieve a specific purpose
P90
- Decorators can be inserted transparently and used without even knowing that you are interacting with them
P104
- Suitable for creating flexible designs that maintain open and close principles
P104
disadvantages
- There are a large number of small classes that can increase code complexity when used
P101
P104
- Rely on a particular type for use, and then suddenly import decorators without thinking everything through
P104
To consider
Our friends at Starbaz decided to start adding coffee sizes to the menu so customers could choose from tall, Grande, venti. Starbaz believes this is a must for any coffee, so getSize() and setSize() have been added to the Beverage category. They also want condiments to be charged according to the size of the coffee, such as $0.10, $0.15 and $0.20 for small and large cups of coffee plus soy milk. How can decorator classes be changed to meet this need? P99
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public int getSize(a) {
return beverage.getSize();
}
public void setSize(int size) {
beverage.setSize(size);
}
public String getDescription(a) {
return beverage.getDescription() + ", Soy";
}
public double cost(a) {
double soyCost = 0.0;
switch (getSize()) {
case TALL:
soyCost = 0.10;
break;
case GRANDE:
soyCost = 0.15;
break;
case VENTI:
soyCost = 0.20;
break;
default:
soyCost = 0.0;
}
returnbeverage.cost() + soyCost; }}Copy the code
thoughts
- The decorator pattern uses inheritance (or implements interfaces), so when supertypes add methods, all subclasses need to change, and design with that in mind
- Always feel familiar decorator pattern, lookjava-design-patterns/decoratorLater,
The idea of discovering decorator patterns is typically implemented using AOP(Finally learned the proxy mode to discover the original dynamic proxy mode)
This post is posted on GitHub: Reading-Notes/Head-First-Design-Patterns