Dark mode
แหล่งอ้างอิง
patterns.dev => https://www.patterns.dev/
refactoring.guru => https://refactoring.guru/
สรุปจาก refactoring
Creational patterns
Singleton pattern
รูปแบบที่รับประกันว่าคลาสจะมีอินสแตนซ์เพียงตัวเดียวและมีจุดเข้าถึงกลาง
ts
// ตัวอย่างโค้ด: src/examples/design-patterns/singleton.ts
import { Database } from "../../../../src/examples/design-patterns/singleton";
// ตัวอย่างการใช้งาน
const db1 = Database.getInstance();
const db2 = Database.getInstance();
console.log(db1 === db2); // true - เป็นอินสแตนซ์เดียวกัน
// ใช้งานเมธอด
const result = db1.query("SELECT * FROM users");
console.log(result);
**ตัวอย่าง**:
```ts
class Database {
private static instance: Database;
private constructor() {
// เชื่อมต่อกับฐานข้อมูล
}
public static getInstance(): Database {
if (!Database.instance) {
Database.instance = new Database();
}
return Database.instance;
}
public query(sql: string): any {
// ค้นหาข้อมูล
}
}
// การใช้งาน
const db1 = Database.getInstance();
const db2 = Database.getInstance();
console.log(db1 === db2); // true - เป็นอินสแตนซ์เดียวกัน
Factory pattern
สร้างอินเตอร์เฟซสำหรับสร้างวัตถุ แต่ให้คลาสย่อยตัดสินใจว่าจะสร้างอินสแตนซ์ของคลาสใด
ts
// ตัวอย่างโค้ด: src/examples/design-patterns/factory.ts
import {
ConcreteProduct1,
ConcreteProduct2,
Creator,
} from "../../../../src/examples/design-patterns/factory";
// ตัวอย่างการใช้งาน
const creator = new Creator();
// สร้าง Product1
const product1 = creator.createProduct("product1");
console.log(product1.operation()); // ConcreteProduct1
// สร้าง Product2
const product2 = creator.createProduct("product2");
console.log(product2.operation()); // ConcreteProduct2
**ตัวอย่าง**:
```ts
interface Product {
operation(): string;
}
class ConcreteProduct1 implements Product {
operation(): string {
return "ConcreteProduct1";
}
}
class ConcreteProduct2 implements Product {
operation(): string {
return "ConcreteProduct2";
}
}
class Creator {
public createProduct(type: string): Product {
if (type === "product1") {
return new ConcreteProduct1();
} else {
return new ConcreteProduct2();
}
}
}
// การใช้งาน
const creator = new Creator();
const product1 = creator.createProduct("product1");
console.log(product1.operation()); // "ConcreteProduct1"
Abstract Factory pattern
สร้างอินเตอร์เฟซสำหรับสร้างครอบครัวของวัตถุที่เกี่ยวข้องกันโดยไม่ต้องระบุคลาสที่แน่นอน
ts
// ตัวอย่างโค้ด: src/examples/design-patterns/abstract-factory.ts
import {
Application,
MacFactory,
WindowsFactory,
} from "../../../../src/examples/design-patterns/abstract-factory";
// ตัวอย่างการใช้งาน Windows UI
const windowsApp = new Application(new WindowsFactory());
windowsApp.createUI();
console.log("Windows UI:");
console.log(windowsApp.renderUI());
// ตัวอย่างการใช้งาน Mac UI
const macApp = new Application(new MacFactory());
macApp.createUI();
console.log("Mac UI:");
console.log(macApp.renderUI());
**ตัวอย่าง**:
```ts
interface Button {
render(): void;
}
interface Checkbox {
render(): void;
}
class WindowsButton implements Button {
render(): void {
console.log("Render Windows button");
}
}
class MacButton implements Button {
render(): void {
console.log("Render Mac button");
}
}
class WindowsCheckbox implements Checkbox {
render(): void {
console.log("Render Windows checkbox");
}
}
class MacCheckbox implements Checkbox {
render(): void {
console.log("Render Mac checkbox");
}
}
interface GUIFactory {
createButton(): Button;
createCheckbox(): Checkbox;
}
class WindowsFactory implements GUIFactory {
createButton(): Button {
return new WindowsButton();
}
createCheckbox(): Checkbox {
return new WindowsCheckbox();
}
}
class MacFactory implements GUIFactory {
createButton(): Button {
return new MacButton();
}
createCheckbox(): Checkbox {
return new MacCheckbox();
}
}
Builder pattern
แยกการสร้างวัตถุที่ซับซ้อนออกจากการแสดงผล เพื่อให้สามารถสร้างวัตถุที่แตกต่างกันได้โดยใช้กระบวนการสร้างเดียวกัน
ตัวอย่าง:
ts
class Car {
seats: number = 0;
engine: string = "";
tripComputer: boolean = false;
gps: boolean = false;
}
class CarBuilder {
private car: Car;
constructor() {
this.reset();
}
public reset(): void {
this.car = new Car();
}
public setSeats(seats: number): CarBuilder {
this.car.seats = seats;
return this;
}
public setEngine(engine: string): CarBuilder {
this.car.engine = engine;
return this;
}
public setTripComputer(hasTripComputer: boolean): CarBuilder {
this.car.tripComputer = hasTripComputer;
return this;
}
public setGPS(hasGPS: boolean): CarBuilder {
this.car.gps = hasGPS;
return this;
}
public getResult(): Car {
const result = this.car;
this.reset();
return result;
}
}
// การใช้งาน
const builder = new CarBuilder();
const sportsCar = builder
.setSeats(2)
.setEngine("SportEngine")
.setTripComputer(true)
.setGPS(true)
.getResult();
Prototype pattern
สร้างวัตถุใหม่โดยการคัดลอกวัตถุที่มีอยู่แล้ว โดยไม่ต้องขึ้นอยู่กับคลาสของวัตถุนั้น
ตัวอย่าง:
ts
interface Prototype {
clone(): Prototype;
}
class ConcretePrototype implements Prototype {
public field1: string;
public field2: number;
constructor(prototype?: ConcretePrototype) {
if (prototype) {
this.field1 = prototype.field1;
this.field2 = prototype.field2;
}
}
public clone(): Prototype {
return new ConcretePrototype(this);
}
}
// การใช้งาน
const original = new ConcretePrototype();
original.field1 = "value";
original.field2 = 42;
const copy = original.clone() as ConcretePrototype;
console.log(copy.field1); // "value"
console.log(copy.field2); // 42
Structural patterns
Adapter
ช่วยให้อินเตอร์เฟซที่เข้ากันไม่ได้สามารถทำงานร่วมกันได้
ตัวอย่าง:
ts
interface Target {
request(): string;
}
class Adaptee {
public specificRequest(): string {
return "Specific request";
}
}
class Adapter implements Target {
private adaptee: Adaptee;
constructor(adaptee: Adaptee) {
this.adaptee = adaptee;
}
public request(): string {
return `Adapter: ${this.adaptee.specificRequest()}`;
}
}
// การใช้งาน
const adaptee = new Adaptee();
const adapter = new Adapter(adaptee);
console.log(adapter.request()); // "Adapter: Specific request"
Bridge
แยกนามธรรมออกจากการนำไปใช้ เพื่อให้ทั้งสองส่วนสามารถเปลี่ยนแปลงได้อย่างอิสระ
ตัวอย่าง:
ts
interface Implementation {
operationImplementation(): string;
}
class ConcreteImplementationA implements Implementation {
operationImplementation(): string {
return "ConcreteImplementationA";
}
}
class ConcreteImplementationB implements Implementation {
operationImplementation(): string {
return "ConcreteImplementationB";
}
}
class Abstraction {
protected implementation: Implementation;
constructor(implementation: Implementation) {
this.implementation = implementation;
}
public operation(): string {
return `Abstraction: ${this.implementation.operationImplementation()}`;
}
}
class ExtendedAbstraction extends Abstraction {
public operation(): string {
return `ExtendedAbstraction: ${this.implementation.operationImplementation()}`;
}
}
Composite
ช่วยให้สามารถจัดเรียงวัตถุในรูปแบบโครงสร้างต้นไม้ และทำงานกับวัตถุเดี่ยวและกลุ่มวัตถุในแบบเดียวกัน
ตัวอย่าง:
ts
abstract class Component {
protected parent: Component | null = null;
public setParent(parent: Component | null): void {
this.parent = parent;
}
public getParent(): Component | null {
return this.parent;
}
public add(component: Component): void {}
public remove(component: Component): void {}
public isComposite(): boolean {
return false;
}
public abstract operation(): string;
}
class Leaf extends Component {
public operation(): string {
return "Leaf";
}
}
class Composite extends Component {
protected children: Component[] = [];
public add(component: Component): void {
this.children.push(component);
component.setParent(this);
}
public remove(component: Component): void {
const index = this.children.indexOf(component);
this.children.splice(index, 1);
component.setParent(null);
}
public isComposite(): boolean {
return true;
}
public operation(): string {
const results = [];
for (const child of this.children) {
results.push(child.operation());
}
return `Branch(${results.join("+")})`;
}
}