iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
JavaScript

入門JavaScript系列 第 21

物件導向應用

  • 分享至 

  • xImage
  •  

JavaScript 物件導向進階應用涉及許多複雜的概念與技巧,可以讓我們更有效地設計和開發大型應用程式。以下是一些 JavaScript 物件導向的應用範例,展示如何將物件導向技巧應用於更實際的場景中。

1. 模組模式(Module Pattern)

模組模式是一種常見的設計模式,用來建立私有變數和方法,同時只暴露必要的公開接口。這種模式在避免全域命名空間污染的同時,可以實現封裝。

範例:模組模式

const CounterModule = (function() {
  let counter = 0;  // 私有變數

  return {
    increment: function() {
      counter++;
      console.log(`Counter: ${counter}`);
    },
    reset: function() {
      counter = 0;
      console.log("Counter reset");
    },
    getCount: function() {
      return counter;
    }
  };
})();

CounterModule.increment(); // Counter: 1
CounterModule.increment(); // Counter: 2
console.log(CounterModule.getCount()); // 2
CounterModule.reset(); // Counter reset
console.log(CounterModule.getCount()); // 0

這裡,我們使用立即執行函式(IIFE)創建了一個私有的 counter,只能透過 increment()reset()getCount() 進行操作,避免了全域範圍內直接訪問 counter

2. 原型繼承與物件共享

使用原型繼承可以讓我們在多個實例之間共享方法,減少內存使用,並促進程式碼重用。

範例:使用原型進行繼承

function Car(make, model) {
  this.make = make;
  this.model = model;
}

Car.prototype.start = function() {
  console.log(`${this.make} ${this.model} is starting...`);
};

Car.prototype.stop = function() {
  console.log(`${this.make} ${this.model} is stopping...`);
};

const myCar = new Car('Toyota', 'Corolla');
myCar.start(); // Toyota Corolla is starting...
myCar.stop();  // Toyota Corolla is stopping...

const anotherCar = new Car('Honda', 'Civic');
anotherCar.start(); // Honda Civic is starting...

這裡,start()stop() 方法被定義在 Car.prototype 上,因此這些方法可以被所有的 Car 實例共享,避免每次創建實例時重複定義這些方法。

3. 工廠模式(Factory Pattern)

工廠模式是一種創建物件的設計模式,用來根據不同的需求創建不同的物件,避免直接使用 new 關鍵字。

範例:工廠模式

function createPerson(type, name) {
  if (type === 'student') {
    return new Student(name);
  } else if (type === 'teacher') {
    return new Teacher(name);
  } else {
    throw new Error('Invalid person type');
  }
}

class Student {
  constructor(name) {
    this.name = name;
    this.role = 'Student';
  }
  
  introduce() {
    console.log(`Hi, I am ${this.name} and I am a ${this.role}.`);
  }
}

class Teacher {
  constructor(name) {
    this.name = name;
    this.role = 'Teacher';
  }

  introduce() {
    console.log(`Hi, I am ${this.name} and I am a ${this.role}.`);
  }
}

const student = createPerson('student', 'Alice');
const teacher = createPerson('teacher', 'Bob');

student.introduce(); // Hi, I am Alice and I am a Student.
teacher.introduce(); // Hi, I am Bob and I am a Teacher.

這裡使用工廠模式動態創建不同類型的物件,根據需求分配合適的類別,簡化了物件的生成邏輯。

4. 單例模式(Singleton Pattern)

單例模式確保一個類只有一個實例,並提供全域訪問點。這在需要共享全域狀態或資源(如設定、資料庫連接等)時很有用。

範例:單例模式

const Singleton = (function() {
  let instance;

  function createInstance() {
    const obj = new Object('I am the instance');
    return obj;
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();

console.log(instance1 === instance2); // true

在這裡,無論呼叫 Singleton.getInstance() 多少次,返回的都是同一個實例,這就是單例模式的核心特性。

5. 策略模式(Strategy Pattern)

策略模式允許一個物件根據需求選擇不同的算法或策略,而不需要在類內部實現所有的邏輯。這有助於將邏輯分解成可替換的單元。

範例:策略模式

class PaymentContext {
  constructor(strategy) {
    this.strategy = strategy;
  }

  execute(amount) {
    return this.strategy.pay(amount);
  }
}

class PayPalStrategy {
  pay(amount) {
    console.log(`Paying ${amount} using PayPal`);
  }
}

class CreditCardStrategy {
  pay(amount) {
    console.log(`Paying ${amount} using Credit Card`);
  }
}

const payPal = new PayPalStrategy();
const creditCard = new CreditCardStrategy();

const paymentContext = new PaymentContext(payPal);
paymentContext.execute(100); // Paying 100 using PayPal

paymentContext.strategy = creditCard;  // 切換策略
paymentContext.execute(200); // Paying 200 using Credit Card

這裡的 PaymentContext 可以接受不同的支付策略(PayPalStrategyCreditCardStrategy),根據需求來執行不同的行為,而不必修改原本的代碼邏輯。

6. 觀察者模式(Observer Pattern)

觀察者模式常見於事件驅動系統,允許物件(觀察者)訂閱其他物件(被觀察者)的變化,當狀態變化時會通知所有訂閱者。這在事件監聽、資料流更新等場景中應用廣泛。

範例:觀察者模式

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  removeObserver(observer) {
    this.observers = this.observers.filter(obs => obs !== observer);
  }

  notifyObservers() {
    this.observers.forEach(observer => observer.update());
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }

  update() {
    console.log(`${this.name} has been notified.`);
  }
}

const subject = new Subject();

const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notifyObservers(); 
// Observer 1 has been notified.
// Observer 2 has been notified.

在這個範例中,Subject 可以通知所有已訂閱的 Observer 當狀態發生改變。這種設計模式非常適合處理事件驅動系統和實時數據更新。

7. 裝飾者模式(Decorator Pattern)

裝飾者模式允許在不改變物件結構的情況下,動態地為物件增加新功能。這可以幫助保持類的簡單,並讓我們能夠根據需求添加功能。

範例:裝飾者模式

class Coffee {
  cost() {
    return 5;
  }
}

class MilkDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  cost() {
    return this.coffee.cost() + 2;
  }
}

class SugarDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  cost() {
    return this.coffee.cost() + 1;
  }
}

let myCoffee = new Coffee();
myCoffee = new MilkDecorator(myCoffee);  // 添加牛奶
myCoffee = new SugarDecorator(myCoffee); // 添加糖

console.log(myCoffee.cost()); // 8

裝飾者模式允許在 Coffee 的基礎上,通過動態添加 MilkDecoratorSugarDecorator 增加功能,而不需要改變 Coffee 類的內部實現。


上一篇
物件導向
下一篇
JavaScript與DOM (1)
系列文
入門JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言