面向对象基础概念

什么是面向对象编程

面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它使用对象来设计应用程序和计算机程序。

// 面向对象编程的核心概念:
// 1. 封装(Encapsulation):将数据和方法组合在一起
// 2. 继承(Inheritance):子类可以继承父类的属性和方法
// 3. 多态(Polymorphism):同一接口可以有不同的实现
// 4. 抽象(Abstraction):隐藏复杂的实现细节

// JavaScript中的对象创建方式

// 1. 对象字面量
const person = {
  name: '张三',
  age: 25,
  greet() {
    return `你好,我是${this.name}`;
  }
};

console.log(person.greet()); // "你好,我是张三"

// 2. 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    return `你好,我是${this.name}`;
  };
}

const person1 = new Person('李四', 30);
console.log(person1.greet()); // "你好,我是李四"

// 3. Object.create()
const personPrototype = {
  greet() {
    return `你好,我是${this.name}`;
  }
};

const person2 = Object.create(personPrototype);
person2.name = '王五';
person2.age = 28;
console.log(person2.greet()); // "你好,我是王五"

// 4. 工厂函数
function createPerson(name, age) {
  return {
    name,
    age,
    greet() {
      return `你好,我是${this.name}`;
    }
  };
}

const person3 = createPerson('赵六', 35);
console.log(person3.greet()); // "你好,我是赵六"

// 5. ES6类语法
class PersonClass {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  greet() {
    return `你好,我是${this.name}`;
  }
}

const person4 = new PersonClass('孙七', 22);
console.log(person4.greet()); // "你好,我是孙七"

// 对象的属性特性
const obj = {};

// 定义属性描述符
Object.defineProperty(obj, 'name', {
  value: '张三',
  writable: true,     // 可写
  enumerable: true,   // 可枚举
  configurable: true  // 可配置
});

// 定义访问器属性
Object.defineProperty(obj, 'fullName', {
  get() {
    return `${this.firstName} ${this.lastName}`;
  },
  set(value) {
    [this.firstName, this.lastName] = value.split(' ');
  },
  enumerable: true,
  configurable: true
});

obj.firstName = '张';
obj.lastName = '三';
console.log(obj.fullName); // "张 三"

obj.fullName = '李 四';
console.log(obj.firstName, obj.lastName); // "李" "四"

// 获取属性描述符
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(descriptor);
// {
//   value: '张三',
//   writable: true,
//   enumerable: true,
//   configurable: true
// }

原型和原型链

// JavaScript使用原型链实现继承

// 构造函数和原型
function Animal(name) {
  this.name = name;
}

// 在原型上添加方法
Animal.prototype.speak = function() {
  return `${this.name} 发出声音`;
};

Animal.prototype.move = function() {
  return `${this.name} 正在移动`;
};

// 创建实例
const animal1 = new Animal('动物1');
const animal2 = new Animal('动物2');

console.log(animal1.speak()); // "动物1 发出声音"
console.log(animal2.speak()); // "动物2 发出声音"

// 所有实例共享原型方法
console.log(animal1.speak === animal2.speak); // true

// 原型链查找
console.log(animal1.hasOwnProperty('name')); // true(实例属性)
console.log(animal1.hasOwnProperty('speak')); // false(原型方法)
console.log('speak' in animal1); // true(在原型链中)

// 动态添加原型方法
Animal.prototype.sleep = function() {
  return `${this.name} 正在睡觉`;
};

// 已创建的实例也能访问新方法
console.log(animal1.sleep()); // "动物1 正在睡觉"

// 原型链继承
function Dog(name, breed) {
  Animal.call(this, name); // 调用父构造函数
  this.breed = breed;
}

// 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 添加子类特有方法
Dog.prototype.bark = function() {
  return `${this.name} 汪汪叫`;
};

// 重写父类方法
Dog.prototype.speak = function() {
  return `${this.name} 汪汪叫`;
};

const dog = new Dog('旺财', '金毛');
console.log(dog.speak()); // "旺财 汪汪叫"(使用重写的方法)
console.log(dog.move());  // "旺财 正在移动"(继承的方法)
console.log(dog.bark());  // "旺财 汪汪叫"(子类特有方法)

// 检查原型链
console.log(dog instanceof Dog);    // true
console.log(dog instanceof Animal); // true
console.log(dog instanceof Object); // true

// 原型链工具函数
function getPrototypeChain(obj) {
  const chain = [];
  let current = obj;
  
  while (current) {
    chain.push(current.constructor.name || 'Object');
    current = Object.getPrototypeOf(current);
  }
  
  return chain;
}

console.log('原型链:', getPrototypeChain(dog));
// ["Dog", "Animal", "Object"]

// 原型污染防护
function createSafeObject(prototype) {
  const obj = Object.create(prototype);
  
  // 防止原型污染
  Object.defineProperty(obj, '__proto__', {
    value: undefined,
    writable: false,
    configurable: false
  });
  
  return obj;
}

// 混入模式(Mixin)
const Flyable = {
  fly() {
    return `${this.name} 正在飞行`;
  },
  
  land() {
    return `${this.name} 正在降落`;
  }
};

const Swimmable = {
  swim() {
    return `${this.name} 正在游泳`;
  },
  
  dive() {
    return `${this.name} 正在潜水`;
  }
};

// 混入函数
function mixin(target, ...sources) {
  sources.forEach(source => {
    Object.getOwnPropertyNames(source).forEach(name => {
      if (name !== 'constructor') {
        Object.defineProperty(target, name, 
          Object.getOwnPropertyDescriptor(source, name));
      }
    });
  });
  return target;
}

// 创建鸟类
function Bird(name) {
  Animal.call(this, name);
}

Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Bird;

// 混入飞行能力
mixin(Bird.prototype, Flyable);

const bird = new Bird('小鸟');
console.log(bird.speak()); // "小鸟 发出声音"
console.log(bird.fly());   // "小鸟 正在飞行"

// 创建鸭子类(既能飞又能游泳)
function Duck(name) {
  Animal.call(this, name);
}

Duck.prototype = Object.create(Animal.prototype);
Duck.prototype.constructor = Duck;

// 混入多种能力
mixin(Duck.prototype, Flyable, Swimmable);

const duck = new Duck('鸭子');
console.log(duck.fly());  // "鸭子 正在飞行"
console.log(duck.swim()); // "鸭子 正在游泳"

ES6类语法

基本类定义

// ES6类提供了更清晰的面向对象语法

class Person {
  // 构造函数
  constructor(name, age, email) {
    this.name = name;
    this.age = age;
    this.email = email;
    this._id = Math.random().toString(36).substr(2, 9);
  }
  
  // 实例方法
  greet() {
    return `你好,我是${this.name},今年${this.age}岁`;
  }
  
  getInfo() {
    return {
      id: this._id,
      name: this.name,
      age: this.age,
      email: this.email
    };
  }
  
  // 访问器属性
  get fullInfo() {
    return `${this.name} (${this.age}岁) - ${this.email}`;
  }
  
  set age(value) {
    if (typeof value !== 'number' || value < 0 || value > 150) {
      throw new Error('年龄必须是0-150之间的数字');
    }
    this._age = value;
  }
  
  get age() {
    return this._age;
  }
  
  // 静态方法
  static createFromString(str) {
    const [name, age, email] = str.split(',');
    return new Person(name.trim(), parseInt(age.trim()), email.trim());
  }
  
  static validateEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  }
  
  // 静态属性
  static species = 'Homo sapiens';
  static #instanceCount = 0; // 私有静态属性
  
  static getInstanceCount() {
    return Person.#instanceCount;
  }
  
  // 私有方法(ES2022)
  #generateId() {
    return Math.random().toString(36).substr(2, 9);
  }
  
  #validateData() {
    if (!this.name || !this.email) {
      throw new Error('姓名和邮箱是必需的');
    }
    if (!Person.validateEmail(this.email)) {
      throw new Error('邮箱格式不正确');
    }
  }
}

// 使用类
const person1 = new Person('张三', 25, 'zhangsan@example.com');
console.log(person1.greet());
console.log(person1.fullInfo);

// 使用静态方法
const person2 = Person.createFromString('李四, 30, lisi@example.com');
console.log(person2.getInfo());

console.log('物种:', Person.species);
console.log('邮箱验证:', Person.validateEmail('test@example.com'));

// 类表达式
const Animal = class {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    return `${this.name} 发出声音`;
  }
};

// 命名类表达式
const Cat = class Feline {
  constructor(name, color) {
    this.name = name;
    this.color = color;
  }
  
  meow() {
    return `${this.name} 喵喵叫`;
  }
  
  // 内部可以使用类名Feline
  getClassName() {
    return Feline.name; // "Feline"
  }
};

const cat = new Cat('小花', '橘色');
console.log(cat.meow());
console.log(cat.getClassName());

// 动态类创建
function createClass(className, methods) {
  const dynamicClass = class {
    constructor(...args) {
      this.args = args;
      this.className = className;
    }
  };
  
  // 添加方法
  Object.keys(methods).forEach(methodName => {
    dynamicClass.prototype[methodName] = methods[methodName];
  });
  
  // 设置类名
  Object.defineProperty(dynamicClass, 'name', {
    value: className
  });
  
  return dynamicClass;
}

const DynamicClass = createClass('MyDynamicClass', {
  greet() {
    return `Hello from ${this.className}`;
  },
  
  getArgs() {
    return this.args;
  }
});

const instance = new DynamicClass('arg1', 'arg2');
console.log(instance.greet());
console.log(instance.getArgs());
console.log(DynamicClass.name); // "MyDynamicClass"

类继承

// 使用extends关键字实现继承

class Animal {
  constructor(name, species) {
    this.name = name;
    this.species = species;
    this.energy = 100;
  }
  
  eat(food) {
    this.energy += 10;
    return `${this.name} 吃了 ${food},能量增加到 ${this.energy}`;
  }
  
  sleep() {
    this.energy += 20;
    return `${this.name} 睡觉了,能量恢复到 ${this.energy}`;
  }
  
  move() {
    this.energy -= 5;
    return `${this.name} 移动了,能量减少到 ${this.energy}`;
  }
  
  getInfo() {
    return {
      name: this.name,
      species: this.species,
      energy: this.energy
    };
  }
  
  // 静态方法
  static compareEnergy(animal1, animal2) {
    return animal1.energy - animal2.energy;
  }
}

// 继承Animal类
class Dog extends Animal {
  constructor(name, breed, owner) {
    super(name, 'Canine'); // 调用父类构造函数
    this.breed = breed;
    this.owner = owner;
    this.loyalty = 100;
  }
  
  // 重写父类方法
  move() {
    this.energy -= 3; // 狗移动消耗更少能量
    return `${this.name} 跑动了,能量减少到 ${this.energy}`;
  }
  
  // 新增方法
  bark() {
    this.energy -= 2;
    return `${this.name} 汪汪叫,能量减少到 ${this.energy}`;
  }
  
  fetch() {
    this.energy -= 10;
    this.loyalty += 5;
    return `${this.name} 捡球回来,忠诚度增加到 ${this.loyalty}`;
  }
  
  // 重写getInfo方法
  getInfo() {
    return {
      ...super.getInfo(), // 调用父类方法
      breed: this.breed,
      owner: this.owner,
      loyalty: this.loyalty
    };
  }
  
  // 静态方法
  static createPuppy(name, breed, owner) {
    const puppy = new Dog(name, breed, owner);
    puppy.energy = 150; // 小狗精力更旺盛
    return puppy;
  }
}

// 使用继承的类
const dog = new Dog('旺财', '金毛', '张三');
console.log(dog.eat('狗粮'));
console.log(dog.bark());
console.log(dog.fetch());
console.log(dog.move());
console.log('狗的信息:', dog.getInfo());

// 创建小狗
const puppy = Dog.createPuppy('小白', '泰迪', '李四');
console.log('小狗信息:', puppy.getInfo());

// 多层继承
class WorkingDog extends Dog {
  constructor(name, breed, owner, job) {
    super(name, breed, owner);
    this.job = job;
    this.workExperience = 0;
  }
  
  work() {
    this.energy -= 15;
    this.workExperience += 1;
    return `${this.name} 执行 ${this.job} 工作,经验增加到 ${this.workExperience}`;
  }
  
  // 重写fetch方法
  fetch() {
    const result = super.fetch();
    this.workExperience += 0.5;
    return result + `,工作经验增加到 ${this.workExperience}`;
  }
  
  getInfo() {
    return {
      ...super.getInfo(),
      job: this.job,
      workExperience: this.workExperience
    };
  }
}

const policeDog = new WorkingDog('警犬', '德牧', '警察局', '缉毒');
console.log(policeDog.work());
console.log(policeDog.fetch());
console.log('警犬信息:', policeDog.getInfo());

// 检查继承关系
console.log('instanceof检查:');
console.log(policeDog instanceof WorkingDog); // true
console.log(policeDog instanceof Dog);        // true
console.log(policeDog instanceof Animal);     // true
console.log(policeDog instanceof Object);     // true

// 抽象基类模式
class Shape {
  constructor(color) {
    if (new.target === Shape) {
      throw new Error('Shape是抽象类,不能直接实例化');
    }
    this.color = color;
  }
  
  // 抽象方法(需要子类实现)
  getArea() {
    throw new Error('getArea方法必须在子类中实现');
  }
  
  getPerimeter() {
    throw new Error('getPerimeter方法必须在子类中实现');
  }
  
  // 具体方法
  getInfo() {
    return {
      type: this.constructor.name,
      color: this.color,
      area: this.getArea(),
      perimeter: this.getPerimeter()
    };
  }
}

class Circle extends Shape {
  constructor(radius, color) {
    super(color);
    this.radius = radius;
  }
  
  getArea() {
    return Math.PI * this.radius * this.radius;
  }
  
  getPerimeter() {
    return 2 * Math.PI * this.radius;
  }
}

class Rectangle extends Shape {
  constructor(width, height, color) {
    super(color);
    this.width = width;
    this.height = height;
  }
  
  getArea() {
    return this.width * this.height;
  }
  
  getPerimeter() {
    return 2 * (this.width + this.height);
  }
}

// 使用具体类
const circle = new Circle(5, '红色');
const rectangle = new Rectangle(4, 6, '蓝色');

console.log('圆形信息:', circle.getInfo());
console.log('矩形信息:', rectangle.getInfo());

// 尝试实例化抽象类会报错
// const shape = new Shape('绿色'); // Error: Shape是抽象类,不能直接实例化

// 工厂模式与继承结合
class ShapeFactory {
  static createShape(type, ...args) {
    switch (type.toLowerCase()) {
      case 'circle':
        return new Circle(...args);
      case 'rectangle':
        return new Rectangle(...args);
      default:
        throw new Error(`不支持的形状类型: ${type}`);
    }
  }
  
  static createShapes(definitions) {
    return definitions.map(def => 
      ShapeFactory.createShape(def.type, ...def.args)
    );
  }
}

// 使用工厂创建形状
const shapes = ShapeFactory.createShapes([
  { type: 'circle', args: [3, '黄色'] },
  { type: 'rectangle', args: [2, 8, '绿色'] },
  { type: 'circle', args: [7, '紫色'] }
]);

shapes.forEach(shape => {
  console.log(shape.getInfo());
});

私有字段和方法

// ES2022引入了私有字段和方法

class BankAccount {
  // 私有字段
  #balance = 0;
  #accountNumber;
  #pin;
  #transactionHistory = [];
  
  // 静态私有字段
  static #bankName = '示例银行';
  static #totalAccounts = 0;
  
  constructor(accountNumber, initialBalance = 0, pin) {
    this.#accountNumber = accountNumber;
    this.#balance = initialBalance;
    this.#pin = pin;
    this.owner = null;
    this.createdAt = new Date();
    
    BankAccount.#totalAccounts++;
    
    this.#addTransaction('开户', initialBalance);
  }
  
  // 私有方法
  #validatePin(pin) {
    return this.#pin === pin;
  }
  
  #addTransaction(type, amount, balance = this.#balance) {
    this.#transactionHistory.push({
      type,
      amount,
      balance,
      timestamp: new Date()
    });
  }
  
  #formatCurrency(amount) {
    return `¥${amount.toFixed(2)}`;
  }
  
  // 公共方法
  deposit(amount, pin) {
    if (!this.#validatePin(pin)) {
      throw new Error('PIN码错误');
    }
    
    if (amount <= 0) {
      throw new Error('存款金额必须大于0');
    }
    
    this.#balance += amount;
    this.#addTransaction('存款', amount);
    
    return {
      success: true,
      message: `成功存入 ${this.#formatCurrency(amount)}`,
      balance: this.#formatCurrency(this.#balance)
    };
  }
  
  withdraw(amount, pin) {
    if (!this.#validatePin(pin)) {
      throw new Error('PIN码错误');
    }
    
    if (amount <= 0) {
      throw new Error('取款金额必须大于0');
    }
    
    if (amount > this.#balance) {
      throw new Error('余额不足');
    }
    
    this.#balance -= amount;
    this.#addTransaction('取款', -amount);
    
    return {
      success: true,
      message: `成功取出 ${this.#formatCurrency(amount)}`,
      balance: this.#formatCurrency(this.#balance)
    };
  }
  
  getBalance(pin) {
    if (!this.#validatePin(pin)) {
      throw new Error('PIN码错误');
    }
    
    return this.#formatCurrency(this.#balance);
  }
  
  getTransactionHistory(pin) {
    if (!this.#validatePin(pin)) {
      throw new Error('PIN码错误');
    }
    
    return this.#transactionHistory.map(transaction => ({
      ...transaction,
      amount: this.#formatCurrency(Math.abs(transaction.amount)),
      balance: this.#formatCurrency(transaction.balance)
    }));
  }
  
  // 访问器属性
  get accountInfo() {
    return {
      accountNumber: this.#accountNumber,
      owner: this.owner,
      createdAt: this.createdAt,
      bankName: BankAccount.#bankName
    };
  }
  
  set owner(value) {
    if (value && typeof value !== 'string') {
      throw new Error('账户所有者必须是字符串');
    }
    this._owner = value;
  }
  
  get owner() {
    return this._owner;
  }
  
  // 静态方法
  static getTotalAccounts() {
    return BankAccount.#totalAccounts;
  }
  
  static getBankName() {
    return BankAccount.#bankName;
  }
  
  // 静态私有方法
  static #generateAccountNumber() {
    return Math.random().toString().substr(2, 10);
  }
  
  static createAccount(owner, initialBalance = 0, pin) {
    const accountNumber = BankAccount.#generateAccountNumber();
    const account = new BankAccount(accountNumber, initialBalance, pin);
    account.owner = owner;
    return account;
  }
}

// 使用银行账户类
const account = BankAccount.createAccount('张三', 1000, '1234');

console.log('账户信息:', account.accountInfo);
console.log('当前余额:', account.getBalance('1234'));

// 进行交易
console.log(account.deposit(500, '1234'));
console.log(account.withdraw(200, '1234'));

// 查看交易历史
console.log('交易历史:', account.getTransactionHistory('1234'));

// 尝试访问私有字段会失败
// console.log(account.#balance); // SyntaxError: Private field '#balance' must be declared in an enclosing class

// 错误的PIN码
try {
  account.getBalance('0000');
} catch (error) {
  console.error('错误:', error.message);
}

console.log('银行总账户数:', BankAccount.getTotalAccounts());

// 继承包含私有字段的类
class SavingsAccount extends BankAccount {
  #interestRate;
  #lastInterestDate;
  
  constructor(accountNumber, initialBalance, pin, interestRate) {
    super(accountNumber, initialBalance, pin);
    this.#interestRate = interestRate;
    this.#lastInterestDate = new Date();
  }
  
  #calculateInterest() {
    const now = new Date();
    const daysSinceLastInterest = Math.floor(
      (now - this.#lastInterestDate) / (1000 * 60 * 60 * 24)
    );
    
    if (daysSinceLastInterest >= 30) {
      // 注意:无法直接访问父类的私有字段
      // 需要通过公共方法获取余额
      const currentBalance = parseFloat(
        this.getBalance(this.#pin).replace('¥', '')
      );
      
      const interest = currentBalance * this.#interestRate / 12;
      return interest;
    }
    
    return 0;
  }
  
  addInterest(pin) {
    const interest = this.#calculateInterest();
    if (interest > 0) {
      this.deposit(interest, pin);
      this.#lastInterestDate = new Date();
      return `添加利息: ¥${interest.toFixed(2)}`;
    }
    return '暂无利息可添加';
  }
  
  get interestRate() {
    return this.#interestRate;
  }
}

// 私有字段的检查
class PrivateFieldChecker {
  #privateField = 'private value';
  
  hasPrivateField(obj) {
    try {
      // 使用in操作符检查私有字段
      return #privateField in obj;
    } catch {
      return false;
    }
  }
  
  static hasPrivateFieldStatic(obj) {
    try {
      return #privateField in obj;
    } catch {
      return false;
    }
  }
}

const checker1 = new PrivateFieldChecker();
const checker2 = new PrivateFieldChecker();
const notChecker = {};

console.log('检查私有字段:');
console.log(checker1.hasPrivateField(checker1)); // true
console.log(checker1.hasPrivateField(checker2)); // true
console.log(checker1.hasPrivateField(notChecker)); // false

设计模式

创建型模式

// 1. 单例模式
class Singleton {
  static #instance = null;
  
  constructor() {
    if (Singleton.#instance) {
      return Singleton.#instance;
    }
    
    this.data = {};
    this.createdAt = new Date();
    Singleton.#instance = this;
  }
  
  static getInstance() {
    if (!Singleton.#instance) {
      Singleton.#instance = new Singleton();
    }
    return Singleton.#instance;
  }
  
  setData(key, value) {
    this.data[key] = value;
  }
  
  getData(key) {
    return this.data[key];
  }
}

// 使用单例
const singleton1 = new Singleton();
const singleton2 = new Singleton();
const singleton3 = Singleton.getInstance();

console.log(singleton1 === singleton2); // true
console.log(singleton1 === singleton3); // true

singleton1.setData('user', '张三');
console.log(singleton2.getData('user')); // "张三"

// 2. 工厂模式
class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }
  
  getInfo() {
    return `${this.name}: ¥${this.price}`;
  }
}

class Book extends Product {
  constructor(name, price, author, pages) {
    super(name, price);
    this.author = author;
    this.pages = pages;
    this.type = 'book';
  }
  
  getInfo() {
    return `${super.getInfo()} - 作者: ${this.author}, 页数: ${this.pages}`;
  }
}

class Electronics extends Product {
  constructor(name, price, brand, warranty) {
    super(name, price);
    this.brand = brand;
    this.warranty = warranty;
    this.type = 'electronics';
  }
  
  getInfo() {
    return `${super.getInfo()} - 品牌: ${this.brand}, 保修: ${this.warranty}年`;
  }
}

class ProductFactory {
  static createProduct(type, config) {
    switch (type) {
      case 'book':
        return new Book(
          config.name,
          config.price,
          config.author,
          config.pages
        );
      case 'electronics':
        return new Electronics(
          config.name,
          config.price,
          config.brand,
          config.warranty
        );
      default:
        throw new Error(`不支持的产品类型: ${type}`);
    }
  }
  
  static createProducts(definitions) {
    return definitions.map(def => 
      ProductFactory.createProduct(def.type, def.config)
    );
  }
}

// 使用工厂模式
const products = ProductFactory.createProducts([
  {
    type: 'book',
    config: {
      name: 'JavaScript高级程序设计',
      price: 89,
      author: 'Matt Frisbie',
      pages: 896
    }
  },
  {
    type: 'electronics',
    config: {
      name: 'iPhone 15',
      price: 5999,
      brand: 'Apple',
      warranty: 1
    }
  }
]);

products.forEach(product => {
  console.log(product.getInfo());
});

// 3. 建造者模式
class Computer {
  constructor() {
    this.cpu = null;
    this.memory = null;
    this.storage = null;
    this.graphics = null;
    this.motherboard = null;
  }
  
  getSpecs() {
    return {
      cpu: this.cpu,
      memory: this.memory,
      storage: this.storage,
      graphics: this.graphics,
      motherboard: this.motherboard
    };
  }
  
  getPrice() {
    const prices = {
      cpu: this.cpu?.price || 0,
      memory: this.memory?.price || 0,
      storage: this.storage?.price || 0,
      graphics: this.graphics?.price || 0,
      motherboard: this.motherboard?.price || 0
    };
    
    return Object.values(prices).reduce((sum, price) => sum + price, 0);
  }
}

class ComputerBuilder {
  constructor() {
    this.computer = new Computer();
  }
  
  setCPU(model, price) {
    this.computer.cpu = { model, price };
    return this;
  }
  
  setMemory(size, type, price) {
    this.computer.memory = { size, type, price };
    return this;
  }
  
  setStorage(type, capacity, price) {
    this.computer.storage = { type, capacity, price };
    return this;
  }
  
  setGraphics(model, memory, price) {
    this.computer.graphics = { model, memory, price };
    return this;
  }
  
  setMotherboard(model, chipset, price) {
    this.computer.motherboard = { model, chipset, price };
    return this;
  }
  
  build() {
    const computer = this.computer;
    this.computer = new Computer(); // 重置建造者
    return computer;
  }
}

// 预设配置的建造者
class GamingComputerBuilder extends ComputerBuilder {
  buildHighEnd() {
    return this
      .setCPU('Intel i9-13900K', 4000)
      .setMemory('32GB', 'DDR5-5600', 1200)
      .setStorage('NVMe SSD', '2TB', 800)
      .setGraphics('RTX 4080', '16GB', 8000)
      .setMotherboard('ASUS ROG', 'Z790', 1500)
      .build();
  }
  
  buildMidRange() {
    return this
      .setCPU('AMD Ryzen 7 7700X', 2500)
      .setMemory('16GB', 'DDR5-5200', 600)
      .setStorage('NVMe SSD', '1TB', 400)
      .setGraphics('RTX 4060 Ti', '8GB', 3500)
      .setMotherboard('MSI B650', 'B650', 800)
      .build();
  }
}

// 使用建造者模式
const builder = new ComputerBuilder();
const customComputer = builder
  .setCPU('Intel i7-13700K', 3000)
  .setMemory('16GB', 'DDR5', 800)
  .setStorage('SSD', '1TB', 500)
  .setGraphics('RTX 4070', '12GB', 4500)
  .setMotherboard('ASUS Prime', 'B760', 600)
  .build();

console.log('自定义电脑配置:', customComputer.getSpecs());
console.log('总价:', customComputer.getPrice());

const gamingBuilder = new GamingComputerBuilder();
const highEndGaming = gamingBuilder.buildHighEnd();
const midRangeGaming = gamingBuilder.buildMidRange();

console.log('高端游戏电脑价格:', highEndGaming.getPrice());
console.log('中端游戏电脑价格:', midRangeGaming.getPrice());

结构型模式

// 1. 适配器模式
class OldPrinter {
  printOldFormat(text) {
    return `[OLD] ${text.toUpperCase()}`;
  }
}

class NewPrinter {
  print(data) {
    return `[NEW] ${data.content} (${data.format})`;
  }
}

// 适配器类
class PrinterAdapter {
  constructor(oldPrinter) {
    this.oldPrinter = oldPrinter;
  }
  
  print(data) {
    // 将新格式转换为旧格式
    const oldFormatText = data.content;
    return this.oldPrinter.printOldFormat(oldFormatText);
  }
}

// 使用适配器
const oldPrinter = new OldPrinter();
const newPrinter = new NewPrinter();
const adapter = new PrinterAdapter(oldPrinter);

const printData = {
  content: 'Hello World',
  format: 'UTF-8'
};

console.log('新打印机:', newPrinter.print(printData));
console.log('适配器:', adapter.print(printData));

// 2. 装饰器模式
class Coffee {
  constructor() {
    this.description = '简单咖啡';
    this.cost = 10;
  }
  
  getDescription() {
    return this.description;
  }
  
  getCost() {
    return this.cost;
  }
}

// 装饰器基类
class CoffeeDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }
  
  getDescription() {
    return this.coffee.getDescription();
  }
  
  getCost() {
    return this.coffee.getCost();
  }
}

// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
  getDescription() {
    return this.coffee.getDescription() + ', 牛奶';
  }
  
  getCost() {
    return this.coffee.getCost() + 3;
  }
}

class SugarDecorator extends CoffeeDecorator {
  getDescription() {
    return this.coffee.getDescription() + ', 糖';
  }
  
  getCost() {
    return this.coffee.getCost() + 1;
  }
}

class WhipDecorator extends CoffeeDecorator {
  getDescription() {
    return this.coffee.getDescription() + ', 奶泡';
  }
  
  getCost() {
    return this.coffee.getCost() + 5;
  }
}

// 使用装饰器
let coffee = new Coffee();
console.log(`${coffee.getDescription()}: ¥${coffee.getCost()}`);

coffee = new MilkDecorator(coffee);
console.log(`${coffee.getDescription()}: ¥${coffee.getCost()}`);

coffee = new SugarDecorator(coffee);
console.log(`${coffee.getDescription()}: ¥${coffee.getCost()}`);

coffee = new WhipDecorator(coffee);
console.log(`${coffee.getDescription()}: ¥${coffee.getCost()}`);

// 3. 代理模式
class RealImage {
  constructor(filename) {
    this.filename = filename;
    this.loadFromDisk();
  }
  
  loadFromDisk() {
    console.log(`从磁盘加载图片: ${this.filename}`);
  }
  
  display() {
    console.log(`显示图片: ${this.filename}`);
  }
}

class ImageProxy {
  constructor(filename) {
    this.filename = filename;
    this.realImage = null;
  }
  
  display() {
    if (!this.realImage) {
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display();
  }
}

// 使用代理模式(延迟加载)
const image1 = new ImageProxy('photo1.jpg');
const image2 = new ImageProxy('photo2.jpg');

console.log('创建代理完成,图片尚未加载');

image1.display(); // 此时才真正加载图片
image1.display(); // 第二次显示,不会重新加载

// 缓存代理
class ExpensiveOperation {
  calculate(n) {
    console.log(`执行复杂计算: ${n}`);
    // 模拟耗时操作
    let result = 0;
    for (let i = 0; i <= n; i++) {
      result += i;
    }
    return result;
  }
}

class CacheProxy {
  constructor(target) {
    this.target = target;
    this.cache = new Map();
  }
  
  calculate(n) {
    if (this.cache.has(n)) {
      console.log(`从缓存获取结果: ${n}`);
      return this.cache.get(n);
    }
    
    const result = this.target.calculate(n);
    this.cache.set(n, result);
    return result;
  }
  
  clearCache() {
    this.cache.clear();
  }
  
  getCacheSize() {
    return this.cache.size;
  }
}

// 使用缓存代理
const operation = new ExpensiveOperation();
const proxy = new CacheProxy(operation);

console.log('结果1:', proxy.calculate(1000));
console.log('结果2:', proxy.calculate(1000)); // 从缓存获取
console.log('结果3:', proxy.calculate(2000));
console.log('缓存大小:', proxy.getCacheSize());

行为型模式

// 1. 观察者模式
class Subject {
  constructor() {
    this.observers = [];
  }
  
  addObserver(observer) {
    this.observers.push(observer);
  }
  
  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index > -1) {
      this.observers.splice(index, 1);
    }
  }
  
  notifyObservers(data) {
    this.observers.forEach(observer => {
      observer.update(data);
    });
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }
  
  update(data) {
    console.log(`${this.name} 收到通知:`, data);
  }
}

// 具体主题
class NewsAgency extends Subject {
  constructor() {
    super();
    this.news = null;
  }
  
  setNews(news) {
    this.news = news;
    this.notifyObservers(news);
  }
  
  getNews() {
    return this.news;
  }
}

// 具体观察者
class NewsChannel extends Observer {
  constructor(name) {
    super(name);
    this.news = null;
  }
  
  update(news) {
    this.news = news;
    console.log(`${this.name} 播报新闻: ${news}`);
  }
}

// 使用观察者模式
const agency = new NewsAgency();
const cnn = new NewsChannel('CNN');
const bbc = new NewsChannel('BBC');
const fox = new NewsChannel('FOX');

agency.addObserver(cnn);
agency.addObserver(bbc);
agency.addObserver(fox);

agency.setNews('重大新闻:JavaScript ES2024发布!');

// 移除观察者
agency.removeObserver(fox);
agency.setNews('后续新闻:新特性详解');

// 2. 策略模式
class PaymentStrategy {
  pay(amount) {
    throw new Error('支付方法必须在子类中实现');
  }
}

class CreditCardPayment extends PaymentStrategy {
  constructor(cardNumber, cvv) {
    super();
    this.cardNumber = cardNumber;
    this.cvv = cvv;
  }
  
  pay(amount) {
    return `使用信用卡 ${this.cardNumber.slice(-4)} 支付 ¥${amount}`;
  }
}

class PayPalPayment extends PaymentStrategy {
  constructor(email) {
    super();
    this.email = email;
  }
  
  pay(amount) {
    return `使用PayPal账户 ${this.email} 支付 ¥${amount}`;
  }
}

class WeChatPayment extends PaymentStrategy {
  constructor(phoneNumber) {
    super();
    this.phoneNumber = phoneNumber;
  }
  
  pay(amount) {
    return `使用微信支付 ${this.phoneNumber} 支付 ¥${amount}`;
  }
}

class PaymentContext {
  constructor(strategy) {
    this.strategy = strategy;
  }
  
  setStrategy(strategy) {
    this.strategy = strategy;
  }
  
  executePayment(amount) {
    return this.strategy.pay(amount);
  }
}

// 使用策略模式
const creditCard = new CreditCardPayment('1234-5678-9012-3456', '123');
const paypal = new PayPalPayment('user@example.com');
const wechat = new WeChatPayment('138-0013-8000');

const paymentContext = new PaymentContext(creditCard);
console.log(paymentContext.executePayment(100));

paymentContext.setStrategy(paypal);
console.log(paymentContext.executePayment(200));

paymentContext.setStrategy(wechat);
console.log(paymentContext.executePayment(300));

// 3. 命令模式
class Command {
  execute() {
    throw new Error('execute方法必须在子类中实现');
  }
  
  undo() {
    throw new Error('undo方法必须在子类中实现');
  }
}

class Light {
  constructor(location) {
    this.location = location;
    this.isOn = false;
  }
  
  turnOn() {
    this.isOn = true;
    console.log(`${this.location} 的灯已打开`);
  }
  
  turnOff() {
    this.isOn = false;
    console.log(`${this.location} 的灯已关闭`);
  }
}

class LightOnCommand extends Command {
  constructor(light) {
    super();
    this.light = light;
  }
  
  execute() {
    this.light.turnOn();
  }
  
  undo() {
    this.light.turnOff();
  }
}

class LightOffCommand extends Command {
  constructor(light) {
    super();
    this.light = light;
  }
  
  execute() {
    this.light.turnOff();
  }
  
  undo() {
    this.light.turnOn();
  }
}

// 遥控器(调用者)
class RemoteControl {
  constructor() {
    this.commands = {};
    this.lastCommand = null;
  }
  
  setCommand(slot, command) {
    this.commands[slot] = command;
  }
  
  pressButton(slot) {
    if (this.commands[slot]) {
      this.commands[slot].execute();
      this.lastCommand = this.commands[slot];
    }
  }
  
  pressUndo() {
    if (this.lastCommand) {
      this.lastCommand.undo();
    }
  }
}

// 使用命令模式
const livingRoomLight = new Light('客厅');
const kitchenLight = new Light('厨房');

const livingRoomLightOn = new LightOnCommand(livingRoomLight);
const livingRoomLightOff = new LightOffCommand(livingRoomLight);
const kitchenLightOn = new LightOnCommand(kitchenLight);
const kitchenLightOff = new LightOffCommand(kitchenLight);

const remote = new RemoteControl();
remote.setCommand('1', livingRoomLightOn);
remote.setCommand('2', livingRoomLightOff);
remote.setCommand('3', kitchenLightOn);
remote.setCommand('4', kitchenLightOff);

remote.pressButton('1'); // 打开客厅灯
remote.pressButton('3'); // 打开厨房灯
remote.pressUndo();      // 撤销上一个命令(关闭厨房灯)
remote.pressButton('2'); // 关闭客厅灯

// 宏命令
class MacroCommand extends Command {
  constructor(commands) {
    super();
    this.commands = commands;
  }
  
  execute() {
    this.commands.forEach(command => command.execute());
  }
  
  undo() {
    // 逆序撤销
    this.commands.slice().reverse().forEach(command => command.undo());
  }
}

// 创建宏命令:同时打开所有灯
const allLightsOn = new MacroCommand([
  livingRoomLightOn,
  kitchenLightOn
]);

const allLightsOff = new MacroCommand([
  livingRoomLightOff,
  kitchenLightOff
]);

remote.setCommand('5', allLightsOn);
remote.setCommand('6', allLightsOff);

remote.pressButton('5'); // 打开所有灯
remote.pressButton('6'); // 关闭所有灯

本章总结

本章深入学习了JavaScript的面向对象编程:

  1. 面向对象基础:理解了OOP的核心概念和JavaScript中的对象创建方式
  2. 原型和原型链:掌握了JavaScript独特的原型继承机制
  3. ES6类语法:学习了现代JavaScript的类定义和继承语法
  4. 私有字段和方法:了解了ES2022引入的真正私有成员
  5. 设计模式:学习了常用的创建型、结构型和行为型设计模式

面向对象编程是构建复杂应用程序的重要方法,通过合理的类设计和设计模式的应用,我们可以编写出更加模块化、可维护和可扩展的代码。

下一章我们将学习JavaScript的错误处理和调试技巧,包括异常处理、调试工具和性能优化等内容。