Abstract Factory Pattern
Posted by Dustin Boston in Design Patterns.
The Abstract Factory Pattern is a creational design pattern that enables the creation of families of related objects without specifying their concrete classes, promoting consistency and flexibility.
The Abstract Factory Pattern is a creational design pattern that provides a way
to create families of related objects without specifying their concrete classes.
This pattern ensures consistency among objects in a family and makes it easier
to add new variants or configurations, promoting flexibility in software design.
Source Code Listing
classes.ts
// AbstractProductA
export abstract class Modal {
constructor(public argument: string) {
console.log(argument);
}
}
// AbstractProductB
export abstract class Button {
constructor(public argument: string) {
console.log(argument);
}
}
// ConcreteProductA1
export class DarkModal extends Modal {}
// ConcreteProductA2
export class DarkButton extends Button {}
// ConcreteProductB1
export class LightModal extends Modal {}
// ConcreteProductB2
export class LightButton extends Button {}
// AbstractFactory
export abstract class ThemedComponent {
abstract createButton(): Button;
abstract createModal(): Modal;
}
// ConcreteFactory1
export class DarkThemedComponent extends ThemedComponent {
createModal(): Modal {
return new DarkModal("DarkModal");
}
createButton(): Button {
return new DarkButton("DarkButton");
}
}
// ConcreteFactory2
export class LightThemedComponent extends ThemedComponent {
createModal(): Modal {
return new LightModal("LightModal");
}
createButton(): Button {
return new LightButton("LightButton");
}
}
export class Client {
modal: Modal;
button: Button;
constructor(factory: ThemedComponent) {
this.modal = factory.createModal();
this.button = factory.createButton();
}
}
components.jsx
import React from "react"; // eslint-disable-line no-unused-vars
import ReactDOM from "react-dom/client";
export const Button = ({background, color, children}) => {
return (
<>
<button type="button" style={{background, color}}>
{children}
</button>
</>
);
};
export const Modal = ({background, color, children}) => {
return (
<>
<dialog style={{background, color}} open>
{children}
</dialog>
</>
);
};
export const DarkButton = ({onClick}) => {
return (
<Button background="gray" color="white" onClick={onClick}>
Dark Button
</Button>
);
};
export const DarkModal = ({children}) => (
<Modal background="black" color="white">
{children}
</Modal>
);
export const DarkThemedComponent = ({type, ...parameters}) =>
type === "modal" ? (
<DarkModal {...parameters} />
) : (
<DarkButton {...parameters} />
);
export const LightButton = ({onClick}) => {
return (
<Button background="white" color="black" onClick={onClick}>
Light Button
</Button>
);
};
export const LightModal = ({children}) => (
<Modal background="white" color="black">
{children}
</Modal>
);
export const LightThemedComponent = ({type, ...parameters}) =>
type === "modal" ? (
<LightModal {...parameters} />
) : (
<LightButton {...parameters} />
);
export const ThemedComponent = ({type, theme, children}) => {
return (
<div>
{theme === "light" && (
<LightThemedComponent type={type}>{children}</LightThemedComponent>
)}
{theme === "dark" && (
<DarkThemedComponent type={type}>{children}</DarkThemedComponent>
)}
</div>
);
};
export const Client = () => (
<>
<ThemedComponent theme="dark" type="modal">
<ThemedComponent theme="dark" type="button" />
</ThemedComponent>
</>
);
// eslint-disable-next-line no-undef
ReactDOM.createRoot(document.querySelector("#root")).render(<Client />);