导航菜单

面向对象设计

面向对象设计(Object-Oriented Design,OOD)是 Microsoft SDE 面试中的重要环节。面试官会要求你设计一个系统或类,考察你的面向对象设计能力、代码组织能力和问题分析能力。

OOD 设计原则

SOLID 原则

1. 单一职责原则(SRP)

一个类应该只有一个引起它变化的原因。

# 不好的设计
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
    
    def save_to_database(self):
        # 保存到数据库
        pass
    
    def send_email(self):
        # 发送邮件
        pass

# 好的设计
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

class UserRepository:
    def save(self, user):
        # 保存到数据库
        pass

class EmailService:
    def send(self, user):
        # 发送邮件
        pass

2. 开放封闭原则(OCP)

对扩展开放,对修改封闭。

# 不好的设计
class AreaCalculator:
    def calculate(self, shape):
        if isinstance(shape, Rectangle):
            return shape.width * shape.height
        elif isinstance(shape, Circle):
            return 3.14 * shape.radius ** 2

# 好的设计
class Shape:
    def area(self):
        raise NotImplementedError

class Rectangle(Shape):
    def area(self):
        return self.width * self.height

class Circle(Shape):
    def area(self):
        return 3.14 * self.radius ** 2

class AreaCalculator:
    def calculate(self, shape):
        return shape.area()

3. 里氏替换原则(LSP)

子类对象应该能够替换父类对象。

class Bird:
    def fly(self):
        pass

class Sparrow(Bird):
    def fly(self):
        print("Sparrow flying")

class Penguin(Bird):
    def fly(self):
        raise NotImplementedError("Penguins can't fly")

# 更好的设计
class Bird:
    pass

class FlyingBird(Bird):
    def fly(self):
        pass

class Sparrow(FlyingBird):
    def fly(self):
        print("Sparrow flying")

class Penguin(Bird):
    pass  # 企鹅不会飞,不需要实现 fly 方法

4. 接口隔离原则(ISP)

客户端不应该依赖它不需要的接口。

# 不好的设计
class Worker:
    def work(self):
        pass
    def eat(self):
        pass

class Human(Worker):
    def work(self):
        print("Human working")
    def eat(self):
        print("Human eating")

class Robot(Worker):
    def work(self):
        print("Robot working")
    def eat(self):
        raise NotImplementedError("Robots don't eat")

# 好的设计
class Workable:
    def work(self):
        raise NotImplementedError

class Eatable:
    def eat(self):
        raise NotImplementedError

class Human(Workable, Eatable):
    def work(self):
        print("Human working")
    def eat(self):
        print("Human eating")

class Robot(Workable):
    def work(self):
        print("Robot working")

5. 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,两者都应该依赖抽象。

# 不好的设计
class MySQLDatabase:
    def save(self, data):
        print("Saving to MySQL")

class UserService:
    def __init__(self):
        self.db = MySQLDatabase()  # 直接依赖具体实现
    
    def save_user(self, user):
        self.db.save(user)

# 好的设计
class Database:
    def save(self, data):
        raise NotImplementedError

class MySQLDatabase(Database):
    def save(self, data):
        print("Saving to MySQL")

class UserService:
    def __init__(self, database: Database):  # 依赖抽象
        self.db = database
    
    def save_user(self, user):
        self.db.save(user)

常见设计模式

1. 单例模式(Singleton)

class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 线程安全的单例
import threading

class ThreadSafeSingleton:
    _instance = None
    _lock = threading.Lock()
    
    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
        return cls._instance

2. 工厂模式(Factory)

class Animal:
    def speak(self):
        raise NotImplementedError

class Dog(Animal):
    def speak(self):
        return "Woof"

class Cat(Animal):
    def speak(self):
        return "Meow"

class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            raise ValueError(f"Unknown animal type: {animal_type}")

3. 观察者模式(Observer)

class Observer:
    def update(self, message):
        raise NotImplementedError

class Subject:
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        self._observers.append(observer)
    
    def detach(self, observer):
        self._observers.remove(observer)
    
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)

class ConcreteObserver(Observer):
    def __init__(self, name):
        self.name = name
    
    def update(self, message):
        print(f"{self.name} received: {message}")

常见 OOD 题目

1. 设计电梯系统

class Elevator:
    def __init__(self, id, current_floor=1):
        self.id = id
        self.current_floor = current_floor
        self.direction = 0  # -1: down, 0: idle, 1: up
        self.requests = []
    
    def move(self):
        if not self.requests:
            self.direction = 0
            return
        
        if self.direction == 1:
            self.current_floor += 1
        elif self.direction == -1:
            self.current_floor -= 1
        
        if self.current_floor in self.requests:
            self.requests.remove(self.current_floor)
            self.stop()
    
    def stop(self):
        print(f"Elevator {self.id} stopped at floor {self.current_floor}")
    
    def add_request(self, floor):
        if floor not in self.requests:
            self.requests.append(floor)
            self.requests.sort()
            if floor > self.current_floor:
                self.direction = 1
            elif floor < self.current_floor:
                self.direction = -1

class ElevatorController:
    def __init__(self, num_elevators):
        self.elevators = [Elevator(i) for i in range(num_elevators)]
    
    def request_elevator(self, floor, direction):
        # 选择最近的电梯
        best_elevator = min(
            self.elevators,
            key=lambda e: abs(e.current_floor - floor)
        )
        best_elevator.add_request(floor)
        return best_elevator

2. 设计停车场系统

from enum import Enum

class VehicleType(Enum):
    MOTORCYCLE = 1
    CAR = 2
    BUS = 3

class Vehicle:
    def __init__(self, license_plate, vehicle_type):
        self.license_plate = license_plate
        self.vehicle_type = vehicle_type

class ParkingSpot:
    def __init__(self, spot_id, vehicle_type):
        self.spot_id = spot_id
        self.vehicle_type = vehicle_type
        self.vehicle = None
        self.is_occupied = False
    
    def park(self, vehicle):
        if self.is_occupied or vehicle.vehicle_type != self.vehicle_type:
            return False
        self.vehicle = vehicle
        self.is_occupied = True
        return True
    
    def leave(self):
        self.vehicle = None
        self.is_occupied = False

class ParkingLot:
    def __init__(self, num_spots_per_type):
        self.spots = {}
        for vehicle_type in VehicleType:
            self.spots[vehicle_type] = [
                ParkingSpot(f"{vehicle_type.name}_{i}", vehicle_type)
                for i in range(num_spots_per_type)
            ]
    
    def park_vehicle(self, vehicle):
        available_spots = [
            spot for spot in self.spots[vehicle.vehicle_type]
            if not spot.is_occupied
        ]
        if not available_spots:
            return False
        return available_spots[0].park(vehicle)
    
    def remove_vehicle(self, vehicle):
        for spots in self.spots.values():
            for spot in spots:
                if spot.vehicle == vehicle:
                    spot.leave()
                    return True
        return False

3. 设计在线书店

class Book:
    def __init__(self, isbn, title, author, price):
        self.isbn = isbn
        self.title = title
        self.author = author
        self.price = price
        self.quantity = 0

class ShoppingCart:
    def __init__(self):
        self.items = {}  # {book: quantity}
    
    def add_item(self, book, quantity):
        if book in self.items:
            self.items[book] += quantity
        else:
            self.items[book] = quantity
    
    def remove_item(self, book):
        if book in self.items:
            del self.items[book]
    
    def get_total(self):
        return sum(book.price * quantity for book, quantity in self.items.items())

class Order:
    def __init__(self, order_id, cart, customer):
        self.order_id = order_id
        self.items = cart.items.copy()
        self.customer = customer
        self.total = cart.get_total()
        self.status = "pending"
    
    def process(self):
        self.status = "processing"
        # 处理订单逻辑
        self.status = "completed"

class Customer:
    def __init__(self, customer_id, name, email):
        self.customer_id = customer_id
        self.name = name
        self.email = email
        self.orders = []
    
    def place_order(self, cart, order_id):
        order = Order(order_id, cart, self)
        order.process()
        self.orders.append(order)
        return order

class BookStore:
    def __init__(self):
        self.books = {}  # {isbn: book}
        self.customers = {}  # {customer_id: customer}
    
    def add_book(self, book):
        self.books[book.isbn] = book
    
    def search_books(self, query):
        results = []
        query_lower = query.lower()
        for book in self.books.values():
            if (query_lower in book.title.lower() or 
                query_lower in book.author.lower()):
                results.append(book)
        return results

OOD 面试技巧

1. 澄清需求

  • 询问功能范围
  • 确认约束条件
  • 了解使用场景

2. 设计步骤

  1. 识别核心对象:找出系统中的主要实体
  2. 定义关系:确定对象之间的关系
  3. 设计接口:定义每个类的公共接口
  4. 实现细节:填充具体实现

3. 代码质量

  • 清晰的命名
  • 适当的注释
  • 错误处理
  • 可扩展性

总结

面向对象设计是面试中的重要环节:

  1. 设计原则:SOLID 原则指导设计
  2. 设计模式:单例、工厂、观察者等常见模式
  3. 常见题目:电梯系统、停车场、在线书店等
  4. 面试技巧:澄清需求、逐步设计、注重代码质量

掌握 OOD 设计能够帮助你设计出清晰、可维护的系统。


接下来,让我们学习系统设计,这是高级工程师面试的重要环节。

搜索