Abstract Factory
- lets you produce families of related object without specifying their concrete classes
- Product families and their variants
- The first thing the Abstract Factory pattern suggests is to explicitly declare interfaces
for each distinct product of the product family
- Then We can make all variants of products follow those interfaces
- The next move is to declare the Abstract Factory - an interface with a list of creation methods
for all products that are part of the product family
- These methods must return abstract product types represented by the interfaces
- A factory is a class that returns products of a particular kind
- 예시
/**
* The Abstract Factory interface declares a set of methods that return
* different abstract products. These products are called a family and are
* related by a high-level theme or concept. Products of one family are usually
* able to collaborate among themselves. A family of products may have several
* variants, but the products of one variant are incompatible with products of
* another.
*/
interface AbstractFactory {
createProductA(): AbstractProductA;
createProductB(): AbstractProductB;
}
/**
* Concrete Factories produce a family of products that belong to a single
* variant. The factory guarantees that resulting products are compatible. Note
* that signatures of the Concrete Factory's methods return an abstract product,
* while inside the method a concrete product is instantiated.
*/
class ConcreteFactory1 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
/**
* Each Concrete Factory has a corresponding product variant.
*/
class ConcreteFactory2 implements AbstractFactory {
public createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
public createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
/**
* Each distinct product of a product family should have a base interface. All
* variants of the product must implement this interface.
*/
interface AbstractProductA {
usefulFunctionA(): string;
}
/**
* These Concrete Products are created by corresponding Concrete Factories.
*/
class ConcreteProductA1 implements AbstractProductA {
public usefulFunctionA(): string {
return 'The result of the product A1.';
}
}
class ConcreteProductA2 implements AbstractProductA {
public usefulFunctionA(): string {
return 'The result of the product A2.';
}
}
/**
* Here's the the base interface of another product. All products can interact
* with each other, but proper interaction is possible only between products of
* the same concrete variant.
*/
interface AbstractProductB {
/**
* Product B is able to do its own thing...
*/
usefulFunctionB(): string;
/**
* ...but it also can collaborate with the ProductA.
*
* The Abstract Factory makes sure that all products it creates are of the
* same variant and thus, compatible.
*/
anotherUsefulFunctionB(collaborator: AbstractProductA): string;
}
/**
* These Concrete Products are created by corresponding Concrete Factories.
*/
class ConcreteProductB1 implements AbstractProductB {
public usefulFunctionB(): string {
return 'The result of the product B1.';
}
/**
* The variant, Product B1, is only able to work correctly with the variant,
* Product A1. Nevertheless, it accepts any instance of AbstractProductA as
* an argument.
*/
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `The result of the B1 collaborating with the (${result})`;
}
}
class ConcreteProductB2 implements AbstractProductB {
public usefulFunctionB(): string {
return 'The result of the product B2.';
}
/**
* The variant, Product B2, is only able to work correctly with the variant,
* Product A2. Nevertheless, it accepts any instance of AbstractProductA as
* an argument.
*/
public anotherUsefulFunctionB(collaborator: AbstractProductA): string {
const result = collaborator.usefulFunctionA();
return `The result of the B2 collaborating with the (${result})`;
}
}
/**
* The client code works with factories and products only through abstract
* types: AbstractFactory and AbstractProduct. This lets you pass any factory or
* product subclass to the client code without breaking it.
*/
function clientCode(factory: AbstractFactory) {
const productA = factory.createProductA();
const productB = factory.createProductB();
console.log(productB.usefulFunctionB());
console.log(productB.anotherUsefulFunctionB(productA));
}
/**
* The client code can work with any concrete factory class.
*/
console.log('Client: Testing client code with the first factory type...');
clientCode(new ConcreteFactory1());
console.log('');
console.log(
'Client: Testing the same client code with the second factory type...'
);
clientCode(new ConcreteFactory2());
- 활용
- Nest.js Factory Pattern (서버)
// main.ts
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// app.module.ts
const typeOrmModuleOptions = {
useFactory: async (
configService: ConfigService,
): Promise<TypeOrmModuleOptions> => ({
namingStrategy: new SnakeNamingStrategy(),
type: 'mysql',
username: configService.get('DB_USERNAME'),
password: configService.get('DB_PASSWORD'),
host: configService.get('DB_HOST'),
port: configService.get('DB_PORT'),
database: configService.get('DB_NAME'),
autoLoadEntities: true,
synchronize: false,
logging: true,
}),
inject: [ConfigService],
};
@Module({
imports: [
TypeOrmModule.forRootAsync(typeOrmModuleOptions),
],
controllers: [],
providers: [],
})
export class AppModule implements NestModule {}
// auth.module.ts
@Module({
imports: [
JwtModule.registerAsync({
useFactory: (config: ConfigService) => ({
secret: config.get<string>('JWT_SECRET_KEY'),
}),
inject: [ConfigService],
}),
],
controllers: [],
providers: [],
exports: [],
})
export class AuthModule {}
반응형
'Personal-Study > Design Patterns' 카테고리의 다른 글
[TS Design Patterns] 구조 패턴 - 어댑터 (2) | 2023.10.23 |
---|---|
[TS Design Patterns] 생성 패턴 - 싱글톤 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 프로토타입 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 빌더 (0) | 2023.10.21 |
[TS Design Patterns] 생성 패턴 - 팩토리 메서드 (0) | 2023.10.21 |
댓글