Идея этого примера состоит в том, чтобы реализовать архитектуру сервиса и репозитория, в которой репозиторий имеет несколько реализаций, прозрачных для сервиса, и все это с использованием структуры внедрения зависимостей и инверсии, предложенной Angular, позволяющей сохранять уровни отдельно от нашего приложения с помощью доменно-ориентированный дизайн.
Слой домена
export default abstract class AuthRepository { abstract login(email: string, password: string): Promise<boolean>; }
Прикладной уровень
import AuthRepository from '../domain/authRepository'; export default class AuthService { constructor(readonly repository: AuthRepository) { this.repository = repository; } async login(email: string, password: string) { const isLogged = await this.repository.login(email, password); return isLogged; } }
Уровень архитектуры
import AuthRepository from '../domain/authRepository'; export default class AuthInMemoryRepository extends AuthRepository { private users = [{ email: '[email protected]', password: '123456' }]; async login(email: string, password: string): Promise<boolean> { const matchUser = this.users.find( (u) => u.email === email && u.password === password ); return matchUser !== undefined; } }
Следующим шагом будет использование Angular injectToken для инверсии зависимостей и построения сервиса, избегая реализации репозитория.
./tokens.ts
import { InjectionToken } from '@angular/core'; import AuthRepository from '../domain/authRepository'; export const AUTH_REPOSITORY_TOKEN = new InjectionToken<AuthRepository>( 'AuthRepository' );
Последним шагом настройки будет указание Angular, как создавать наши экземпляры и какие классы использовать при инверсии зависимостей.
./app.module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import AuthService from 'src/core/application/authService'; import AuthInMemoryRepository from 'src/core/architecture/authInMemoryRepository'; import { AUTH_REPOSITORY_TOKEN } from 'src/core/architecture/tokens'; import AuthRepository from 'src/core/domain/authRepository'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, AppRoutingModule, FormsModule, ReactiveFormsModule], providers: [ { provide: AUTH_REPOSITORY_TOKEN, useClass: AuthInMemoryRepository, }, { provide: AuthService, useFactory: (authRepository: AuthRepository) => { return new AuthService(authRepository); }, deps: [AUTH_REPOSITORY_TOKEN], }, ], bootstrap: [AppComponent], }) export class AppModule {}
В завершение мы просто импортируем сервис в наш компонент, а angular automanticante внедряет реализацию репозитория.
./app.comComponent.ts
import { Component } from '@angular/core'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import AuthService from 'src/core/application/authService'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { constructor(private service: AuthService) {} public form = new FormGroup({ email: new FormControl('', [Validators.required, Validators.email]), password: new FormControl('', [Validators.required]), }); async onSubmit() { const { email, password } = this.form.value; if (email && password) { const isLogged = await this.service.login(email, password); alert(isLogged ? 'Logged' : 'Not logged'); } } }
Pero compartir no es amoral – es un emperativo моральный. Только то, что было сказано, чтобы код был неверен, и ему пришлось сделать копию с другом.
- Аарон Шварц