Skip to content

Commit 05f86a7

Browse files
PatrickPatrick
authored andcommitted
feature(): add decorator pattern
1 parent 4d0415d commit 05f86a7

File tree

11 files changed

+235
-45
lines changed

11 files changed

+235
-45
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
22
parser: '@typescript-eslint/parser',
33
parserOptions: {
4-
project: 'tsconfig.base.json',
4+
project: 'tsconfig.json',
55
ecmaVersion: 2020,
66
sourceType: 'module'
77
},

src/app/09. Decorator/decorator.module.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import { CommonModule } from '@angular/common';
33

44
import { DecoratorRoutingModule } from './decorator-routing.module';
55
import { DecoratorComponent } from './decorator/decorator.component';
6-
6+
import { AngularMaterialModule } from '../modules/angular-material.module';
7+
import { FormsModule } from '@angular/forms';
78

89
@NgModule({
910
declarations: [DecoratorComponent],
10-
imports: [
11-
CommonModule,
12-
DecoratorRoutingModule
13-
]
11+
imports: [CommonModule, DecoratorRoutingModule, AngularMaterialModule, FormsModule]
1412
})
15-
export class DecoratorModule { }
13+
export class DecoratorModule {}
Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,38 @@
1-
<p>decorator works!</p>
1+
<div class="container">
2+
<h1>
3+
Decorator Pattern
4+
</h1>
5+
<div class="content">
6+
<mat-card>
7+
<mat-card-title>
8+
Pizza Calculator
9+
</mat-card-title>
10+
<mat-card-subtitle>
11+
Current price: {{ price }}
12+
</mat-card-subtitle>
13+
<mat-divider></mat-divider>
14+
<mat-card-content>
15+
<label id="radio-group"><b>Pick your favorite pizza</b></label>
16+
<mat-radio-group
17+
aria-labelledby="radio-group"
18+
[(ngModel)]="pizza">
19+
<mat-radio-button class="example-radio-button" *ngFor="let pizza of pizzas" [value]="pizza">
20+
<div>{{ pizza.getTopping() }}</div>
21+
</mat-radio-button>
22+
</mat-radio-group>
23+
</mat-card-content>
24+
<mat-card-actions *ngIf="pizza != null">
25+
<button mat-raised-button color="primary" (click)="btnCheese()">With cheese</button>
26+
<button mat-raised-button color="primary" (click)="btnMushrooms()">With mushrooms</button>
27+
<button mat-raised-button color="primary" (click)="btnJalapeno()">With jalapeno</button>
28+
<button mat-raised-button color="primary" (click)="btnCheeseAndJalapeno()">With cheese & jalapeno</button>
29+
<button mat-raised-button color="primary" (click)="btnCheeseAndMushrooms()">With cheese & mushrooms</button>
30+
</mat-card-actions>
31+
<mat-card-footer>
32+
<div *ngFor="let topping of toppings">
33+
{{ topping }}
34+
</div>
35+
</mat-card-footer>
36+
</mat-card>
37+
</div>
38+
</div>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
button {
2+
margin-top: 5px !important;
3+
}
4+
5+
div {
6+
text-align: center;
7+
}
8+
9+
div.container {
10+
display: flex;
11+
flex-direction: column;
12+
align-items: center;
13+
}
14+
15+
div.content {
16+
display: flex;
17+
flex-direction: row;
18+
}
19+
20+
label {
21+
margin-bottom: 15px;
22+
}
23+
24+
mat-card-content {
25+
display: flex;
26+
flex-direction: column;
27+
padding-top: 15px;
28+
align-items: center;
29+
}
30+
31+
mat-radio-group {
32+
display: flex;
33+
}
34+
35+
.mat-radio-button ~ .mat-radio-button {
36+
margin-left: 16px;
37+
}
Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,65 @@
11
import { Component, OnInit } from '@angular/core';
2+
import { Margherita, Pizza, Detroit, Fugazzeta } from '../models/pizza.model';
3+
import {
4+
ExtraCheeseToppingDecorator,
5+
JalapenoToppingDecorator,
6+
MushroomToppingDecorator
7+
} from '../models/topping.decorator';
28

39
@Component({
410
selector: 'app-decorator',
511
templateUrl: './decorator.component.html',
612
styleUrls: ['./decorator.component.scss']
713
})
8-
export class DecoratorComponent implements OnInit {
14+
export class DecoratorComponent {
15+
public price: number;
16+
public toppings: string[];
17+
public pizzas: Pizza[];
918

10-
constructor() { }
19+
public pizza: Pizza;
1120

12-
ngOnInit(): void {
21+
constructor() {
22+
this.price = 0;
23+
this.toppings = new Array<string>();
24+
this.initPizzas();
1325
}
1426

27+
public btnCheese(): void {
28+
const decorator = new ExtraCheeseToppingDecorator(this.pizza);
29+
this.logOrder(decorator);
30+
}
31+
32+
public btnMushrooms(): void {
33+
const decorator = new MushroomToppingDecorator(this.pizza);
34+
this.logOrder(decorator);
35+
}
36+
37+
public btnJalapeno(): void {
38+
const decorator = new JalapenoToppingDecorator(this.pizza);
39+
this.logOrder(decorator);
40+
}
41+
42+
public btnCheeseAndJalapeno(): void {
43+
const cheeseDecorator = new ExtraCheeseToppingDecorator(this.pizza);
44+
const cheeseAndJalapenoDecorator = new JalapenoToppingDecorator(cheeseDecorator);
45+
this.logOrder(cheeseAndJalapenoDecorator);
46+
}
47+
48+
public btnCheeseAndMushrooms(): void {
49+
const cheeseDecorator = new ExtraCheeseToppingDecorator(this.pizza);
50+
const cheeseAndMushroomDecorator = new MushroomToppingDecorator(cheeseDecorator);
51+
this.logOrder(cheeseAndMushroomDecorator);
52+
}
53+
54+
private logOrder(decorator: Pizza) {
55+
this.price = decorator.getPrice();
56+
this.toppings.push(decorator.getTopping());
57+
}
58+
59+
private initPizzas() {
60+
this.pizzas = new Array<Pizza>();
61+
this.pizzas.push(new Margherita());
62+
this.pizzas.push(new Detroit());
63+
this.pizzas.push(new Fugazzeta());
64+
}
1565
}

src/app/09. Decorator/models/email.decorator.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/app/09. Decorator/models/notifier.model.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// inspired by https://stackoverflow.com/a/2707425
2+
3+
export interface Pizza {
4+
getPrice(): number;
5+
getTopping(): string;
6+
}
7+
8+
class BasePizza implements Pizza {
9+
protected price: number;
10+
protected topping: string;
11+
12+
public getPrice(): number {
13+
return this.price;
14+
}
15+
16+
public getTopping(): string {
17+
return this.topping;
18+
}
19+
}
20+
21+
export class Margherita extends BasePizza implements Pizza {
22+
constructor() {
23+
super();
24+
this.price = 5.95;
25+
this.topping = 'Pizza Margherita';
26+
}
27+
}
28+
29+
export class Detroit extends BasePizza implements Pizza {
30+
constructor() {
31+
super();
32+
this.price = 7.99;
33+
this.topping = 'Pizza Detroit';
34+
}
35+
}
36+
37+
export class Fugazzeta extends BasePizza implements Pizza {
38+
constructor() {
39+
super();
40+
this.price = 6.89;
41+
this.topping = 'Pizza Fugazzeta';
42+
}
43+
}

src/app/09. Decorator/models/sms.decorator.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { Pizza } from './pizza.model';
2+
3+
export class ExtraCheeseToppingDecorator implements Pizza {
4+
readonly priceCheese: number = 1.3;
5+
protected pizza: Pizza;
6+
7+
constructor(pizzaToDecorate: Pizza) {
8+
this.pizza = pizzaToDecorate;
9+
}
10+
11+
public getPrice(): number {
12+
return this.pizza.getPrice() + this.priceCheese;
13+
}
14+
15+
public getTopping(): string {
16+
return this.pizza.getTopping() + '.. with extra cheese';
17+
}
18+
}
19+
20+
export class MushroomToppingDecorator implements Pizza {
21+
readonly priceMushrooms: number = 0.9;
22+
protected pizza: Pizza;
23+
24+
constructor(pizzaToDecorate: Pizza) {
25+
this.pizza = pizzaToDecorate;
26+
}
27+
28+
public getPrice(): number {
29+
return this.pizza.getPrice() + this.priceMushrooms;
30+
}
31+
32+
public getTopping(): string {
33+
return this.pizza.getTopping() + '.. with extra mushrooms';
34+
}
35+
}
36+
37+
export class JalapenoToppingDecorator implements Pizza {
38+
readonly priceJalapeno: number = 1.5;
39+
protected pizza: Pizza;
40+
41+
constructor(pizzaToDecorate: Pizza) {
42+
this.pizza = pizzaToDecorate;
43+
}
44+
45+
public getPrice(): number {
46+
return this.pizza.getPrice() + this.priceJalapeno;
47+
}
48+
49+
public getTopping(): string {
50+
return this.pizza.getTopping() + '.. with extra jalapeno';
51+
}
52+
53+
public extraHot(): number {
54+
return 0.8;
55+
}
56+
}

src/app/xx. components/Home/home/home.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
<a mat-raised-button [routerLink]="['/facade']" routerLinkActive="facade" color="primary">
3434
Facade
3535
</a>
36+
<a mat-raised-button [routerLink]="['/decorator']" routerLinkActive="decorator" color="primary">
37+
Decorator
38+
</a>
3639
</mat-card-content>
3740
</mat-card>
3841

0 commit comments

Comments
 (0)