Table of Contents
Comprendere il modello di fabbrica in angolare
Le applicazioni moderne angolari richiedono spesso forme che si adattano a ruoli utente diversi, schemi di dati o ambienti di configurazione. La creazione manuale di istanze per ogni permutazione porta a codice duplicato, casi di commutazione fragili e logica di validazione aggrovigliata. Il modello di fabbrica si rivolge a questo fornendo un meccanismo centralizzato per produrre oggetti di forma basati su un tipo o configurazione definita.
La fabbrica incapsula la logica di istanza, quindi i componenti non devono più sapere quale classe forma per istantanare o come assemblare i controlli. Questa separazione delle preoccupazioni rende la base di codice più modulare, testabile e scalabile — soprattutto quando il numero di tipi di forma cresce oltre una manciata. Il modello si inserisce naturalmente nel sistema di iniezione di dipendenza di Angular, permettendo di registrare le funzioni di fabbrica come fornitori e iniettarle dove necessario.
Perché utilizzare il modello di fabbrica per forme dinamiche?
Angular già fornisce il per gestire scenari di forma complessi, ma il modello di fabbrica elimina la caldaia procedurale che spesso accompagna la creazione di forme.
- Riduce duplicazione del codice. Invece di ripetere costruzioni simili [[] tra componenti o servizi, centralizzare la logica in un metodo di fabbrica. Ogni tipo di forma è costruito da una classe di costruttore dedicata, quindi scrivi la sua logica solo una volta.
- Amportare una nuova forma significa creare una nuova classe di costruttori e registrarla in fabbrica. Non è necessario cambiare i componenti esistenti, finché richiedono moduli per tipo.
- Configurazioni di forma flessibili. La fabbrica può accettare parametri aggiuntivi (ad esempio, autorizzazioni utente, località o bandiere di caratteristiche) che influenzano i controlli inclusi o come vengono convalidati.
- Supporta interfacce utente dinamiche. Quando il tipo di modulo viene determinato a runtime (ad esempio, da un record di database o da un parametro di percorso), la fabbrica lo rende banale per istantanare il corretto in volo.
- Migliora la testabilità.[ Ogni costruttore di forme può essere testato in modo indipendente. La fabbrica stessa diventa una semplice mappatura che può essere inumidito o storto nei test dei componenti.
Questi vantaggi sono particolarmente preziosi nelle applicazioni aziendali che devono supportare molti flussi di lavoro distinti, ciascuno con la propria serie di campi e regole di validazione.
Procedura di implementazione del core
Passo 1: Definire forma tipo di Enumerazione e Interfacce
Iniziare definendo un insieme di tipi di forma. Utilizzando un enum previene i tipi di tipo e fornisce un contratto chiaro:
export enum FormType {
Login = 'login',
Registration = 'registration',
Feedback = 'feedback',
Contact = 'contact'
}
Successivamente, definire un'interfaccia che tutti i costruttori di forma implementano, in modo che la fabbrica possa trattarli in modo polimorfo:
import { FormGroup } from '@angular/forms';
export interface FormBuilderInterface {
build(config?: any): FormGroup;
}
Il parametro opzionale consente ai costruttori di personalizzare il modulo in base ai dati runtime, come valori pre-riempimento o regolando le regole di validazione per il ruolo dell'utente.
Passo 2: Creare modelli di calcestruzzo
Ogni costruttore di cemento implementa e restituisce un corretto configurato [. Ad esempio, un costruttore di moduli di login potrebbe assomigliare a questo:
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
export class LoginFormBuilder implements FormBuilderInterface {
private fb: FormBuilder;
constructor() {
this.fb = new FormBuilder();
}
build(): FormGroup {
return this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(6)]],
rememberMe: [false]
});
}
}
Un costruttore di moduli di registrazione potrebbe includere controlli aggiuntivi e convalida cross-field:
export class RegistrationFormBuilder implements FormBuilderInterface {
private fb: FormBuilder;
constructor() {
this.fb = new FormBuilder();
}
build(): FormGroup {
const form = this.fb.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8)]],
confirmPassword: ['', Validators.required]
}, { validators: this.matchPasswords });
return form;
}
private matchPasswords(group: FormGroup): { [key: string]: any } | null {
const password = group.get('password')?.value;
const confirm = group.get('confirmPassword')?.value;
return password === confirm ? null : { mismatch: true };
}
}
Questa struttura si bilancia in modo pulito: ogni costruttore si concentra esclusivamente sui dettagli della propria forma, e si può riutilizzare la logica componendo i costruttori o utilizzando le funzioni di helper.
Passo 3: costruire la classe di fabbrica
La classe di fabbrica è responsabile della mappatura di un tipo di modulo al relativo costruttore corrispondente. Una semplice implementazione utilizza un'indicazione di commutazione o un oggetto di mappa:
import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormType } from './form-type.enum';
import { LoginFormBuilder } from './login-form.builder';
import { RegistrationFormBuilder } from './registration-form.builder';
import { FeedbackFormBuilder } from './feedback-form.builder';
@Injectable({ providedIn: 'root' })
export class FormFactory {
private builders = new Map<FormType, FormBuilderInterface>();
constructor() {
// Register builders
this.builders.set(FormType.Login, new LoginFormBuilder());
this.builders.set(FormType.Registration, new RegistrationFormBuilder());
this.builders.set(FormType.Feedback, new FeedbackFormBuilder());
}
createForm(type: FormType, config?: any): FormGroup {
const builder = this.builders.get(type);
if (!builder) {
throw new Error(`No builder registered for form type: ${type}`);
}
return builder.build(config);
}
}
Registrare i costruttori all’interno del costruttore è semplice, ma per applicazioni più grandi si potrebbe preferire l’utilizzo di iniezione di dipendenza di Angular per fornire ai costruttori.
Passo 4: Utilizzare la fabbrica in componenti
Con la fabbrica in posizione, i componenti possono richiedere un'istanza di forma senza conoscere i dettagli della sua costruzione, ad esempio un componente che gestisce più tipi di forma in base a un parametro di percorso:
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormFactory } from './form.factory';
import { FormType } from './form-type.enum';
@Component({
selector: 'app-dynamic-form',
template: `