angular: wzorzec strategii

omówię:
- jak zaimplementować wzorzec strategii
Wzorzec strategii jest jednym z najpopularniejszych wzorców jakie wykorzystuje się w projektach.
W tym artykule chciałbym przedstawić prostą implementację tego wzorca. W etapie 4 procesu w lekcji 6 będziemy dodawać wzorzec do aplikacji, którą będziemy tworzyć w poszczególnych lekcjach.
Stworzymy funkcjonalność przydzielania zniżki danemu klientowi. Zniżka będzie przydzielana na podstawie kilku danych takich jak: czy klient posiada firmę czy jest klientem prywatnym, wiek klienta oraz jak długo posiada prawo jazdy.
Utworzymy dwie strategie: biznesową oraz prywatną. Zniżka biznesowa będzie zależna od czasu prowadzenia firmy. Zniżka prywatna od wieku klienta oraz czasu posiadanego prawa jazdy.
W katalogu src/app stwórz katalog strategy a w nim interfejs client.interface.ts
export interface Client {
name: string;
businessInMonths?: number;
isUnder25?: boolean;
licenseInMonths?: number;
}
Kolejnym krokiem będzie stworzenie interfejsu strategii oferty. Stwórz plik offer-strategy.interface.ts
import { Client } from './client.interface';
export interface OfferStrategy {
isDiscountAvailable(client: Client): boolean;
getDiscount(client: Client): number;
}
Utwórz pierwszą z naszych strategii business-offer-strategy.ts
import { OfferStrategy } from './offer-strategy.interface';
import { Client } from './client.interface';
export class BusinessOfferStrategy implements OfferStrategy {
isDiscountAvailable(client: Client): boolean {
return client.businessInMonths > 6;
}
getDiscount(client: Client): number {
if (!this.isDiscountAvailable(client)) {
return 0;
}
const businessInMonths = client.businessInMonths;
if (businessInMonths >= 6 && businessInMonths < 12) {
return 4;
}
if (businessInMonths > 60) {
return 30;
}
return businessInMonths * 0.4;
}
}
oraz strategię dla klienta prywatnego private-offer-strategy.ts
import { OfferStrategy } from './offer-strategy.interface';
import { Client } from './client.interface';
export class PrivateOfferStrategy implements OfferStrategy {
isDiscountAvailable(client: Client): boolean {
return !client.isUnder25 && client.licenseInMonths > 24;
}
getDiscount(client: Client): number {
if (!this.isDiscountAvailable(client)) {
return 0;
}
const licenseInMonths = client.licenseInMonths;
if (licenseInMonths > 60) {
return 15;
}
return licenseInMonths * 0.2;
}
}
Mamy już dwie strategie odpowiedzialne za obsługę klientów biznesowych oraz indywidualnych. Potrzebujemy jeszcze serwisu który będzie się zajmował wyliczeniem składki na podstawie danych o kliencie.
Utwórz discount.service.ts
import { Injectable } from '@angular/core';
import { Client } from './client.interface';
import { OfferStrategy } from './offer-strategy.interface';
import { BusinessOfferStrategy } from './business-offer-strategy';
import { PrivateOfferStrategy } from './private-offer-strategy';
@Injectable(
{
providedIn: 'root'
}
)
export class DiscountService {
public getDiscount(client: Client): number {
return this.resolveStrategy(client).getDiscount(client);
}
private resolveStrategy(client: Client): OfferStrategy {
if (client.businessInMonths) {
return new BusinessOfferStrategy();
}
return new PrivateOfferStrategy();
}
}
W src/app stwórz folder car oraz dodaj plik car.model.ts
export class Car {
constructor(public brand: string,
public model: string,
public engineType: string,
public type: string) {
}
}
Ostatnie dwie rzeczy jakie zostały to wstrzyknięcie discount.service.ts w app.componet.ts jak poniżej oraz przygotowanie kilku klientów i wyliczenie dla nich zniżki.
import {Component, OnInit} from '@angular/core';
import {DiscountService} from './strategy/discount.service';
import {Car} from './car/car.model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
public car: Car;
public car1: Car;
public karolDiscount: number;
public jacekDiscount: number;
public wojtekDiscount: number;
public dawidDiscount: number;
constructor(private discountService: DiscountService) {
}
public ngOnInit(): void {
this.car = new Car(
'Audi',
'A6',
'benzyna',
'sedan'
);
this.car1 = new Car(
'Mercedes',
'Klasa E',
'diesel',
'coupe'
);
const karol = {
name: 'Karol',
businessInMonths: 15
};
const jacek = {
name: 'Jacek',
businessInMonths: 60
};
const wojtek = {
name: 'Wojtek',
isUnder25: false,
licenseInMonths: 40
};
const dawid = {
name: 'Dawid',
isUnder25: false,
licenseInMonths: 35
};
this.karolDiscount = this.discountService.getDiscount(karol);
this.jacekDiscount = this.discountService.getDiscount(jacek);
this.wojtekDiscount = this.discountService.getDiscount(wojtek);
this.dawidDiscount = this.discountService.getDiscount(dawid);
}
}
oraz app.component.html
<p>Marka: {{car.brand}}</p>
<p>Model: {{car.model}}</p>
<p>Silnik: {{car.engineType}}</p>
<p>Nadwozie: {{car.type}}</p>
<br>
<p>Marka: {{car1.brand}}</p>
<p>Model: {{car1.model}}</p>
<p>Silnik: {{car1.engineType}}</p>
<p>Nadwozie: {{car1.type}}</p>
<br>
<p>Karol otrzyma: {{karolDiscount}}% zniżki</p>
<p>Jacek otrzyma: {{jacekDiscount}}% zniżki</p>
<p>Wojtek otrzyma: {{wojtekDiscount}}% zniżki</p>
<p>Dawid otrzyma: {{dawidDiscount}}% zniżki</p>