Dark mode
แหล่งอ้างอิง
patterns.dev => https://www.patterns.dev/
refactoring.guru => https://refactoring.guru/
สรุปจาก refactoring
Creational patterns
Singleton pattern
รูปแบบที่รับประกันว่าคลาสจะมีอินสแตนซ์เพียงตัวเดียวและมีจุดเข้าถึงกลาง
ตัวอย่าง:
typescript
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
สร้างอินเตอร์เฟซสำหรับสร้างวัตถุ แต่ให้คลาสย่อยตัดสินใจว่าจะสร้างอินสแตนซ์ของคลาสใด
ตัวอย่าง:
typescript
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
สร้างอินเตอร์เฟซสำหรับสร้างครอบครัวของวัตถุที่เกี่ยวข้องกันโดยไม่ต้องระบุคลาสที่แน่นอน
ตัวอย่าง:
typescript
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
แยกการสร้างวัตถุที่ซับซ้อนออกจากการแสดงผล เพื่อให้สามารถสร้างวัตถุที่แตกต่างกันได้โดยใช้กระบวนการสร้างเดียวกัน
ตัวอย่าง:
typescript
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
สร้างวัตถุใหม่โดยการคัดลอกวัตถุที่มีอยู่แล้ว โดยไม่ต้องขึ้นอยู่กับคลาสของวัตถุนั้น
ตัวอย่าง:
typescript
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
ช่วยให้อินเตอร์เฟซที่เข้ากันไม่ได้สามารถทำงานร่วมกันได้
ตัวอย่าง:
typescript
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
แยกนามธรรมออกจากการนำไปใช้ เพื่อให้ทั้งสองส่วนสามารถเปลี่ยนแปลงได้อย่างอิสระ
ตัวอย่าง:
typescript
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
ช่วยให้สามารถจัดเรียงวัตถุในรูปแบบโครงสร้างต้นไม้ และทำงานกับวัตถุเดี่ยวและกลุ่มวัตถุในแบบเดียวกัน
ตัวอย่าง:
typescript
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("+")})`;
}
}