面向对象基础概念
什么是面向对象编程
面向对象编程(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的面向对象编程:
- 面向对象基础:理解了OOP的核心概念和JavaScript中的对象创建方式
- 原型和原型链:掌握了JavaScript独特的原型继承机制
- ES6类语法:学习了现代JavaScript的类定义和继承语法
- 私有字段和方法:了解了ES2022引入的真正私有成员
- 设计模式:学习了常用的创建型、结构型和行为型设计模式
面向对象编程是构建复杂应用程序的重要方法,通过合理的类设计和设计模式的应用,我们可以编写出更加模块化、可维护和可扩展的代码。
下一章我们将学习JavaScript的错误处理和调试技巧,包括异常处理、调试工具和性能优化等内容。