You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 2工厂模式实现及模板复用、按需构建配置咨询

Hey there! Great question—combining factory patterns with reusable templates in Angular 2 (now part of the broader Angular ecosystem) is a smart way to keep your code DRY and scalable. Let’s break this down into three key areas to solve your problem:

1. Template Organization: Shared + Vehicle-Specific UI

For your use case (common elements like tires/windows plus exclusive features for cars/buses/trucks), content projection (using <ng-content>) is the most flexible approach to reuse a base template while injecting custom content. Here’s how to set it up:

Step 1: Create a Base Vehicle Component

This component holds all your shared UI and logic:

// vehicle-base.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-vehicle-base',
  template: `
    <div class="vehicle-container">
      <!-- Shared UI Elements -->
      <div class="shared-features">
        <h3>General Vehicle</h3>
        <p>Tires: {{ tireCount }}</p>
        <p>Windows: {{ windowCount }}</p>
        <button (click)="rollUpAllWindows()">Roll Up Windows</button>
      </div>

      <!-- Slot for Vehicle-Specific Content -->
      <div class="specific-features">
        <ng-content></ng-content>
      </div>
    </div>
  `,
  styles: [`
    .vehicle-container { border: 1px solid #eee; padding: 1rem; margin: 1rem 0; }
    .shared-features { background: #f5f5f5; padding: 0.5rem; margin-bottom: 1rem; }
  `]
})
export class VehicleBaseComponent {
  @Input() tireCount: number;
  @Input() windowCount: number;

  rollUpAllWindows() {
    console.log("All windows rolled up!");
    // Add shared window control logic here
  }
}

Step 2: Build Vehicle-Specific Components

Each vehicle component will wrap the base component and inject its own exclusive UI/logic:

// car.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-car',
  template: `
    <app-vehicle-base [tireCount]="4" [windowCount]="4">
      <!-- Car-Exclusive Content -->
      <h4>Car Features</h4>
      <p>Doors: 4</p>
      <button (click)="activateCruiseControl()">Enable Cruise Control</button>
    </app-vehicle-base>
  `
})
export class CarComponent {
  activateCruiseControl() {
    console.log("Cruise control activated!");
    // Add car-specific logic here
  }
}

Repeat this pattern for BusComponent (e.g., add passenger door controls) and TruckComponent (e.g., trailer hitch controls)—all reusing the base template’s shared elements.

2. Implementing the Factory Pattern in Angular

Since you already know TypeScript’s factory basics, let’s adapt this to Angular’s dependency injection (DI) system (critical for managing services/components with dependencies):

Step 1: Define a Vehicle Interface

Create a contract for all vehicle types:

// vehicle.interface.ts
export interface Vehicle {
  getVehicleType(): string;
  activateSpecialFeature(): void;
}

Step 2: Build Vehicle Services

Each vehicle type gets its own service implementing the interface:

// car.service.ts
import { Injectable } from '@angular/core';
import { Vehicle } from './vehicle.interface';

@Injectable()
export class CarService implements Vehicle {
  getVehicleType(): string {
    return "Car";
  }

  activateSpecialFeature(): void {
    console.log("Car: Activating cruise control!");
  }
}

Do the same for BusService and TruckService with their unique features.

Step 3: Create the Vehicle Factory

Use Angular’s Injector to instantiate services (avoids manual new calls which break DI):

// vehicle-factory.service.ts
import { Injectable, Injector } from '@angular/core';
import { Vehicle } from './vehicle.interface';
import { CarService } from './car.service';
import { BusService } from './bus.service';
import { TruckService } from './truck.service';

@Injectable()
export class VehicleFactoryService {
  constructor(private injector: Injector) {}

  createVehicle(type: string): Vehicle {
    switch(type) {
      case "car":
        return this.injector.get(CarService);
      case "bus":
        return this.injector.get(BusService);
      case "truck":
        return this.injector.get(TruckService);
      default:
        throw new Error(`Unknown vehicle type: ${type}`);
    }
  }
}

Step 4: Use the Factory in a Component

// vehicle-manager.component.ts
import { Component } from '@angular/core';
import { VehicleFactoryService } from './vehicle-factory.service';
import { Vehicle } from './vehicle.interface';

@Component({
  selector: 'app-vehicle-manager',
  template: `
    <button (click)="createVehicle('car')">Spawn Car</button>
    <button (click)="createVehicle('bus')">Spawn Bus</button>
    <button (click)="createVehicle('truck')">Spawn Truck</button>
    <p *ngIf="currentVehicle">Active Vehicle: {{ currentVehicle.getVehicleType() }}</p>
  `
})
export class VehicleManagerComponent {
  currentVehicle: Vehicle;

  constructor(private vehicleFactory: VehicleFactoryService) {}

  createVehicle(type: string) {
    this.currentVehicle = this.vehicleFactory.createVehicle(type);
    this.currentVehicle.activateSpecialFeature();
  }
}
3. Build Config: Extracting Specific Modules/Features

To split your app into modular chunks (for faster loads and better maintainability), use Angular’s built-in lazy loading and chunk splitting:

Lazy Load Vehicle Modules

Organize each vehicle type into its own module, then configure routing to load them on demand:

// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { 
    path: 'car', 
    loadChildren: () => import('./car/car.module').then(m => m.CarModule) 
  },
  { 
    path: 'bus', 
    loadChildren: () => import('./bus/bus.module').then(m => m.BusModule) 
  },
  { 
    path: 'truck', 
    loadChildren: () => import('./truck/truck.module').then(m => m.TruckModule) 
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

Fine-Tune Chunk Splitting

In your angular.json config, you can customize how chunks are split (e.g., group shared code into a single chunk):

{
  "projects": {
    "your-app-name": {
      "architect": {
        "build": {
          "options": {
            "optimization": true,
            "splitChunks": {
              "chunks": "all",
              "cacheGroups": {
                "vehicle-shared": {
                  "test": /[\\/]vehicle-base[\\/]/,
                  "name": "vehicle-shared",
                  "chunks": "all"
                }
              }
            }
          }
        }
      }
    }
  }
}

This will bundle all shared vehicle base code into a separate vehicle-shared.js chunk, which is reused across all vehicle modules.


内容的提问来源于stack exchange,提问作者Veena Mohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:16:26