Skip to content

Commit 8d2e07f

Browse files
committed
added coffee decorator example to decorator
1 parent 1b12e2c commit 8d2e07f

File tree

2 files changed

+73
-8
lines changed

2 files changed

+73
-8
lines changed

structural_design_pattern/decorator/README.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,25 @@ also Known as `wrapper`
33
> - structural pattern.
44
> - allows a user to add new functionality to an existing object without altering (Changing) its structure.
55
6-
<table>
6+
<table align="center">
77
<tr>
8-
<td><img src = "assets/Decorator_UML_class_diagram.png" ></td>
8+
<td><img style="background-color:#33475b" src = "assets/Decorator_UML_class_diagram.png" ></td>
99
<td><img src = "assets/decorator_structure.png" ></td>
1010
</tr>
1111
</table>
1212

1313
## Sections
1414
- [Definitions](#Definitions)
15-
- [What problems can it solve?](#What-problems-can-it-solve?)
16-
- [What solution does it describe?](#What-solution-does-it-describe?)
15+
- [What problems can it solve](#What-problems-can-it-solve)
16+
- [What solution does it describe](#What-solution-does-it-describe)
1717
- [Examples](#Examples)
1818
- [Shape Decorator Example](#Shape-Decorator-Example)
1919
- [Windows Decorator Example](#Windows-Decorator-Example)
2020
- [Email Notifier Example](#Email-Notifier-Example)
21+
- [Coffee Decorator Example](#Coffee-Decorator-Example)
2122
- [TO DO](#TO-DO)
2223
- [Summery](#Summery)
24+
- [Sources](#Sources)
2325

2426

2527
## Definitions
@@ -44,23 +46,23 @@ also Known as `wrapper`
4446
- because an object's behavior can be augmented without defining an entirely new object.
4547

4648

47-
## What problems can it solve?
49+
## What problems can it solve
4850
1. Responsibilities should be added to (and removed from) an object dynamically at run-time.
4951
2. A flexible alternative (Changing) to subclassing for extending functionality should be provided.
5052
- When using subclassing, different subclasses extend a class in different ways.
5153
- `But an extension is bound (restricted) to the class at compile-time and can't be changed at run-time.`
5254

53-
## What solution does it describe?
55+
## What solution does it describe
5456
1. implement the interface of the extended (decorated) object (Component) transparently by forwarding all requests to it
5557
perform additional functionality before/after forwarding a request.
5658
2. This allows working with different Decorator objects to extend the functionality of an object dynamically at run-time.
5759

5860
> See also the UML class and sequence diagram below.
59-
<center><img src = "assets/Decorator_Design_Pattern_UML.jpg"></center>
61+
<p align="center" ><img src = "assets/Decorator_Design_Pattern_UML.jpg"></p>
6062
6163
## Examples
6264

63-
### Shape Decorator
65+
### Shape Decorator Example
6466
> in this example we will decorate a shape with some color
6567
> without alter (Change) shape class.
6668
@@ -278,6 +280,9 @@ void main(List<String> args) {
278280
### Email Notifier Example
279281
- Example in dart: <a href="email_notifier_example/" target="_blank"> click here </a>
280282

283+
### Coffee Decorator Example
284+
- Example in dart: <a href="coffee_decorator_example.dart" target="_blank"> click here </a>
285+
- Example Source: https://github.com/scottt2/design-patterns-in-dart/tree/master/decorator
281286

282287
## TO Do
283288
https://refactoring.guru/design-patterns/decorator
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
abstract class Beverage {
2+
double get cost;
3+
String get ingredients;
4+
}
5+
6+
class Ingredient {
7+
double cost;
8+
String name;
9+
10+
Ingredient(this.name, this.cost);
11+
12+
@override
13+
String toString() => name;
14+
}
15+
16+
var coffee = Ingredient("coffee", .25);
17+
var milk = Ingredient("milk", .5);
18+
var sugar = Ingredient("sugar", .1);
19+
20+
class Coffee implements Beverage {
21+
final Set<Ingredient> _ingredients = {coffee, milk, sugar};
22+
23+
@override
24+
double get cost =>
25+
_ingredients.fold(0, (total, ingredient) => total + ingredient.cost);
26+
27+
@override
28+
String get ingredients {
29+
var stringIngredients = _ingredients.fold<String>("", (total, ingredient) {
30+
if (_ingredients.last.name == ingredient.name) {
31+
return total + "and ${ingredient.name}";
32+
}
33+
return total + "${ingredient.name}, ";
34+
});
35+
36+
return stringIngredients;
37+
}
38+
}
39+
40+
class StarbucksCoffeeDecorator implements Beverage {
41+
final Beverage _coffee = Coffee();
42+
43+
@override
44+
double get cost => _coffee.cost * 5;
45+
46+
@override
47+
String get ingredients => _coffee.ingredients;
48+
}
49+
50+
void main() {
51+
var coffee = Coffee();
52+
var starbucksCoffee = StarbucksCoffeeDecorator();
53+
54+
print("Coffee contains ${coffee.ingredients}. It costs \$${coffee.cost}");
55+
print(
56+
"Starbucks coffee contains ${starbucksCoffee.ingredients}. It costs \{starbucksCoffee.cost}");
57+
58+
// Coffee contains coffee, milk, and sugar. It costs $0.85
59+
// Starbucks coffee contains coffee, milk, and sugar. It costs $4.25
60+
}

0 commit comments

Comments
 (0)