一、什么是面向对象编程?
1.1 面向对象编程的定义
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式或编程思想。它将现实世界的事物抽象为程序中的"对象",通过对象之间的交互来设计和构建软件系统。面向对象编程的核心思想是将数据(属性)和操作数据的方法(行为)封装在一个单元中,这个单元就是我们所说的对象。
1.2 面向对象的本质特征
面向对象编程的本质是对现实世界的建模。在现实世界中,任何事物都可以被看作是一个对象,每个对象都有自己的特征和行为。例如,一辆汽车是一个对象,它有颜色、品牌、型号等特征,还有启动、刹车、转向等行为。面向对象编程就是将这种现实世界的思维模式应用到程序设计中。
1.3 与面向过程编程的区别
面向过程编程以过程为中心,思考的是"如何一步步地解决问题",而面向对象编程以对象为中心,思考的是"有哪些对象参与解决问题"。面向过程编程更加注重算法和流程,而面向对象编程更加注重对象的结构和交互。
二、面向对象编程干什么?
· 解决软件复杂性问题
随着软件系统规模的增长,复杂度呈指数级上升。面向对象编程通过封装、继承、多态等机制,将复杂的系统分解为相对独立的对象,每个对象负责自己的职责,从而有效地控制了系统的复杂度。
·提高代码的可维护性
面向对象编程通过模块化和封装,使得代码更容易理解和维护。当需求发生变化时,只需要修改相关的对象类,而不影响其他部分。这种局部修改的特性大大降低了维护成本。
·增强代码的可重用性
面向对象编程通过继承和组合,可以重用已有的代码。我们可以创建基类,然后在子类中扩展功能,或者将已有的对象组合成新的对象,避免重复开发相同的功能。
·提升开发效率
面向对象编程提供了一种更加自然的思考方式,使得开发者可以更好地理解和表达业务逻辑。同时,丰富的类库和框架也是基于面向对象思想构建的,开发者可以直接使用这些现成的组件,提高开发效率。
三、面向对象编程怎么用?
3.1 核心概念的使用
三大核心概念:
·继承
·封装
·多态
3.1.1 类与对象
类是对象的模板或蓝图,定义了一类对象共同具有的属性和方法。对象是类的实例,是具体存在的个体。在使用时,首先定义类,然后创建类的实例(对象),最后通过对象调用方法和访问属性。
代码示例:
java
// 定义一个Person类
public class Person {
// 属性
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 方法
public void introduce() {
System.out.println("我叫" + name + ",今年" + age + "岁");
}
// getter和setter方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
// 创建对象并使用
public class Main {
public static void main(String[] args) {
// 创建Person对象
Person person1 = new Person("张三", 25);
Person person2 = new Person("李四", 30);
// 调用方法
person1.introduce(); // 输出:我叫张三,今年25岁
person2.introduce(); // 输出:我叫李四,今年30岁
}
}
3.1.2 封装
封装是指将对象的内部实现细节隐藏起来,只暴露必要的接口给外部使用。通过访问修饰符(如private、protected、public)来控制访问权限,保护对象内部状态不被随意修改。
封装示例:
python
class BankAccount:
def __init__(self, account_number, initial_balance=0):
self.__account_number = account_number # 私有属性
self.__balance = initial_balance # 私有属性
def deposit(self, amount):
"""存款方法"""
if amount > 0:
self.__balance += amount
print(f"存款成功,当前余额:{self.__balance}")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
"""取款方法"""
if amount > 0 and amount <= self.__balance:
self.__balance -= amount
print(f"取款成功,当前余额:{self.__balance}")
else:
print("取款失败,金额不足或无效")
def get_balance(self):
"""获取余额(只读访问)"""
return self.__balance
def get_account_number(self):
"""获取账号(只读访问)"""
return self.__account_number
# 使用示例
account = BankAccount("123456789", 1000)
account.deposit(500) # 存款成功,当前余额:1500
account.withdraw(200) # 取款成功,当前余额:1300
print(account.get_balance()) # 1300
# 下面这些访问会报错,因为属性是私有的
# print(account.__balance) # AttributeError
# account.__balance = 5000 # 不会影响实际余额
3.1.3 继承
继承允许一个类获取另一个类的属性和方法,实现代码的重用。子类可以继承父类的特性,并且可以添加新的特性或重写父类的方法。继承体现了"is-a"的关系。
继承示例:
cpp
#include <iostream>
#include <string>
using namespace std;
// 基类:动物
class Animal {
protected:
string name;
int age;
public:
Animal(string name, int age) : name(name), age(age) {}
virtual void makeSound() {
cout << name << "发出声音" << endl;
}
void eat() {
cout << name << "正在吃东西" << endl;
}
virtual ~Animal() {}
};
// 派生类:狗
class Dog : public Animal {
private:
string breed;
public:
Dog(string name, int age, string breed)
: Animal(name, age), breed(breed) {}
void makeSound() override { // 重写父类方法
cout << name << "汪汪叫" << endl;
}
void wagTail() { // 子类特有方法
cout << name << "摇尾巴" << endl;
}
void displayInfo() {
cout << "品种:" << breed << ",姓名:" << name << ",年龄:" << age << endl;
}
};
// 派生类:猫
class Cat : public Animal {
private:
bool isIndoor;
public:
Cat(string name, int age, bool indoor)
: Animal(name, age), isIndoor(indoor) {}
void makeSound() override { // 重写父类方法
cout << name << "喵喵叫" << endl;
}
void climb() { // 子类特有方法
cout << name << "爬树" << endl;
}
};
int main() {
Dog dog("小白", 3, "金毛");
Cat cat("小黑", 2, true);
dog.makeSound(); // 小白汪汪叫
dog.eat(); // 小白正在吃东西
dog.wagTail(); // 小白摇尾巴
cat.makeSound(); // 小黑喵喵叫
cat.eat(); // 小黑正在吃东西
cat.climb(); // 小黑爬树
return 0;
}
3.1.4 多态
多态允许不同类的对象对相同的消息做出不同的响应。通过方法重写和接口实现,同一种操作可以作用于不同的对象,产生不同的执行结果。多态提高了程序的灵活性和可扩展性。
多态示例:
javascript
// 定义形状接口
class Shape {
calculateArea() {
throw new Error("子类必须实现此方法");
}
calculatePerimeter() {
throw new Error("子类必须实现此方法");
}
display() {
console.log(`这是一个${this.constructor.name},面积:${this.calculateArea().toFixed(2)},周长:${this.calculatePerimeter().toFixed(2)}`);
}
}
// 圆形类
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
calculateArea() {
return Math.PI * this.radius * this.radius;
}
calculatePerimeter() {
return 2 * Math.PI * this.radius;
}
}
// 矩形类
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
calculateArea() {
return this.width * this.height;
}
calculatePerimeter() {
return 2 * (this.width + this.height);
}
}
// 三角形类
class Triangle extends Shape {
constructor(base, height, side1, side2, side3) {
super();
this.base = base;
this.height = height;
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
calculateArea() {
return 0.5 * this.base * this.height;
}
calculatePerimeter() {
return this.side1 + this.side2 + this.side3;
}
}
// 多态的使用
function processShapes(shapes) {
shapes.forEach(shape => {
shape.display(); // 同样的调用,不同的行为
});
}
// 创建不同形状的对象
const shapes = [
new Circle(5),
new Rectangle(4, 6),
new Triangle(3, 4, 3, 4, 5)
];
// 多态调用
processShapes(shapes);
/*
输出:
这是一个Circle,面积:78.54,周长:31.42
这是一个Rectangle,面积:2500,周长:20.00
这是一个Triangle,面积:6.00,周长:12.00
*/
多态的优势表格:
| 优势 | 说明 | 代码示例 |
|---|---|---|
| 灵活性 | 可以轻松添加新的类型而不修改现有代码 | 添加新的Shape子类即可 |
| 可扩展性 | 系统可以适应需求变化 | 通过继承扩展功能 |
| 代码复用 | 统一的处理逻辑可以处理多种类型 | processShapes函数处理所有形状 |
| 降低耦合 | 客户端代码只依赖抽象接口 | 依赖Shape接口而非具体实现 |
四、设计原则的应用
4.1 单一职责原则
一个类应该只有一个引起变化的原因。在实际开发中,我们需要确保每个类都只负责一个特定的功能,避免将不相关的功能混合在同一个类中。
单一职责原则示例:
typescript
// 违反单一职责原则的例子
class User {
private name: string;
private email: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
}
// 用户属性相关
getName(): string { return this.name; }
setName(name: string): void { this.name = name; }
// 用户验证逻辑(职责1)
validateEmail(): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(this.email);
}
// 数据库操作(职责2)
saveToDatabase(): void {
console.log(`保存用户 ${this.name} 到数据库`);
}
// 邮件发送(职责3)
sendWelcomeEmail(): void {
console.log(`发送欢迎邮件给 ${this.email}`);
}
}
// 遵循单一职责原则的重构
class UserProfile {
private name: string;
private email: string;
constructor(name: string, email: string) {
this.name = name;
this.email = email;
}
getName(): string { return this.name; }
setName(name: string): void { this.name = name; }
getEmail(): string { return this.email; }
setEmail(email: string): void { this.email = email; }
}
class UserValidator {
static validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
static validateUser(user: UserProfile): boolean {
return this.validateEmail(user.getEmail()) && user.getName().length > 0;
}
}
class UserRepository {
static save(user: UserProfile): void {
console.log(`保存用户 ${user.getName()} 到数据库`);
}
}
class EmailService {
static sendWelcomeEmail(user: UserProfile): void {
console.log(`发送欢迎邮件给 ${user.getEmail()}`);
}
}
4.2 开放封闭原则
软件实体应该对扩展开放,对修改封闭。当需求发生变化时,我们应该通过添加新的代码来扩展功能,而不是修改现有的代码。
开放封闭原则示例:
csharp
// 违反开放封闭原则的设计
public class AreaCalculator
{
public double CalculateArea(object shape)
{
if (shape is Rectangle)
{
var rect = (Rectangle)shape;
return rect.Width * rect.Height;
}
else if (shape is Circle)
{
var circle = (Circle)shape;
return Math.PI * circle.Radius * circle.Radius;
}
// 每添加新形状都需要修改这个类
else if (shape is Triangle)
{
var triangle = (Triangle)shape;
return 0.5 * triangle.Base * triangle.Height;
}
return 0;
}
}
// 遵循开放封闭原则的设计
public interface IShape
{
double CalculateArea();
}
public class Rectangle : IShape
{
public double Width { get; set; }
public double Height { get; set; }
public double CalculateArea()
{
return Width * Height;
}
}
public class Circle : IShape
{
public double Radius { get; set; }
public double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
public class Triangle : IShape
{
public double Base { get; set; }
public double Height { get; set; }
public double CalculateArea()
{
return 0.5 * Base * Height;
}
}
// 新增形状不需要修改现有代码
public class Trapezoid : IShape
{
public double TopBase { get; set; }
public double BottomBase { get; set; }
public double Height { get; set; }
public double CalculateArea()
{
return 0.5 * (TopBase + BottomBase) * Height;
}
}
public class AreaCalculator
{
public double CalculateTotalArea(List<IShape> shapes)
{
double totalArea = 0;
foreach (var shape in shapes)
{
totalArea += shape.CalculateArea();
}
return totalArea;
}
}
4.3 里氏替换原则
子类必须能够替换其基类,并且不会产生错误。这意味着子类应该完全兼容父类的接口,保证程序的正确性不会因为使用子类而受到影响。
里氏替换原则示例:
go
package main
import "fmt"
// 违反里氏替换原则的例子
type Bird interface {
Fly()
MakeSound()
}
type Sparrow struct{}
func (s *Sparrow) Fly() {
fmt.Println("麻雀在飞翔")
}
func (s *Sparrow) MakeSound() {
fmt.Println("麻雀叽叽喳喳叫")
}
type Penguin struct{}
func (p *Penguin) Fly() {
panic("企鹅不会飞!") // 这里破坏了里氏替换原则
}
func (p *Penguin) MakeSound() {
fmt.Println("企鹅嘎嘎叫")
}
// 遵循里氏替换原则的重构
type Animal interface {
MakeSound()
}
type Flyable interface {
Fly()
}
type Swimmable interface {
Swim()
}
type Sparrow struct{}
func (s *Sparrow) MakeSound() {
fmt.Println("麻雀叽叽喳喳叫")
}
func (s *Sparrow) Fly() {
fmt.Println("麻雀在飞翔")
}
type Penguin struct{}
func (p *Penguin) MakeSound() {
fmt.Println("企鹅嘎嘎叫")
}
func (p *Penguin) Swim() {
fmt.Println("企鹅在游泳")
}
func LetBirdFly(bird Flyable) {
bird.Fly()
}
func LetAnimalMakeSound(animal Animal) {
animal.MakeSound()
}
func main() {
sparrow := &Sparrow{}
penguin := &Penguin{}
LetAnimalMakeSound(sparrow) // 麻雀叽叽喳喳叫
LetAnimalMakeSound(penguin) // 企鹅嘎嘎叫
LetBirdFly(sparrow) // 麻雀在飞翔
// LetBirdFly(penguin) // 编译错误:Penguin没有实现Flyable接口
}
4.4 接口隔离原则
不应该强迫客户依赖于它们不使用的方法。在设计接口时,应该将大接口拆分为多个小接口,让客户只需要知道它们感兴趣的方法。
接口隔离原则示例:
swift
// 违反接口隔离原则的大接口
protocol Worker {
func work()
func eat()
func sleep()
func code()
func design()
func test()
}
// 所有员工都要实现所有方法,即使某些方法对他们没有意义
class Developer: Worker {
func work() { print("开发人员在工作") }
func eat() { print("开发人员在吃饭") }
func sleep() { print("开发人员在睡觉") }
func code() { print("开发人员在写代码") }
func design() { print("开发人员在设计 - 不是主要职责") }
func test() { print("开发人员在测试 - 不是主要职责") }
}
// 遵循接口隔离原则的设计
protocol BasicWorker {
func work()
func eat()
func sleep()
}
protocol Coder {
func code()
}
protocol Designer {
func design()
}
protocol Tester {
func test()
}
class Developer: BasicWorker, Coder {
func work() { print("开发人员在工作") }
func eat() { print("开发人员在吃饭") }
func sleep() { print("开发人员在睡觉") }
func code() { print("开发人员在写代码") }
}
class Designer: BasicWorker, Designer {
func work() { print("设计师在工作") }
func eat() { print("设计师在吃饭") }
func sleep() { print("设计师在睡觉") }
func design() { print("设计师在设计") }
}
class FullStackDeveloper: BasicWorker, Coder, Designer, Tester {
func work() { print("全栈开发在工作") }
func eat() { print("全栈开发在吃饭") }
func sleep() { print("全栈开发在睡觉") }
func code() { print("全栈开发在写代码") }
func design() { print("全栈开发在设计") }
func test() { print("全栈开发在测试") }
}
4.5 依赖倒置原则
高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。通过依赖注入、接口编程等方式实现这一原则。
依赖倒置原则示例:
kotlin
// 违反依赖倒置原则
class LightBulb {
fun turnOn() {
println("灯泡亮了")
}
fun turnOff() {
println("灯泡灭了")
}
}
class Switch {
private val bulb = LightBulb() // 直接依赖具体实现
fun press() {
bulb.turnOn()
}
fun release() {
bulb.turnOff()
}
}
// 遵循依赖倒置原则
interface Switchable {
fun turnOn()
fun turnOff()
}
class LightBulb : Switchable {
override fun turnOn() {
println("灯泡亮了")
}
override fun turnOff() {
println("灯泡灭了")
}
}
class Fan : Switchable {
override fun turnOn() {
println("风扇开始转动")
}
override fun turnOff() {
println("风扇停止转动")
}
}
class Switch(private val device: Switchable) { // 依赖抽象
fun press() {
device.turnOn()
}
fun release() {
device.turnOff()
}
}
// 使用依赖注入
class SmartHome {
private val lightSwitch = Switch(LightBulb())
private val fanSwitch = Switch(Fan())
fun operateDevices() {
lightSwitch.press() // 灯泡亮了
fanSwitch.press() // 风扇开始转动
lightSwitch.release() // 灯泡灭了
fanSwitch.release() // 风扇停止转动
}
}
SOLID原则对比表:
| 原则 | 英文名 | 核心思想 | 解决的问题 |
|---|---|---|---|
| 单一职责 | SRP | 一个类只负责一个职责 | 职责混乱,代码耦合 |
| 开放封闭 | OCP | 对扩展开放,对修改封闭 | 需求变化导致的频繁修改 |
| 里氏替换 | LSP | 子类可以替换父类 | 继承关系不当导致的错误 |
| 接口隔离 | ISP | 接口要小而专 | 接口冗余,强制依赖不需要的方法 |
| 依赖倒置 | DIP | 依赖抽象而非具体实现 | 高层模块与低层模块强耦合 |
4.6 实践步骤
需求分析
在开始面向对象设计之前,首先要充分理解业务需求。识别系统中的主要实体、实体间的关系、以及它们的行为。
对象识别
通过需求分析,识别出系统中的候选对象。可以使用名词短语法,从需求文档中找出名词,这些名词通常是潜在的类。
类设计
设计类的结构,包括属性和方法。确定每个类的职责,定义类之间的关系(关联、依赖、聚合、组合等)。
接口定义
为复杂的类定义接口,隐藏实现细节,提供稳定的对外契约。接口设计要遵循最小化原则,只暴露必要的方法。
实现与测试
根据设计编写代码,然后进行单元测试和集成测试,确保每个对象的行为符合预期,对象间的协作正常工作。
五、面向对象编程的应用场景
5.1 电子商务系统
电子商务系统涉及用户管理、商品管理、订单处理、支付结算等多个模块,每个模块都可以设计为独立的对象。通过面向对象的设计,可以很好地处理这些复杂的业务逻辑,并支持系统的扩展和维护。
电商系统类图示例:
java
// 用户相关类
public class User {
private Long userId;
private String username;
private String email;
private List<Address> addresses;
private ShoppingCart cart;
public void addToCart(Product product, int quantity) {
cart.addItem(product, quantity);
}
public Order placeOrder() {
return new Order(this, cart.getItems());
}
}
public class Product {
private Long productId;
private String name;
private BigDecimal price;
private int stock;
private Category category;
public boolean isAvailable() {
return stock > 0;
}
public void reduceStock(int quantity) {
if (stock >= quantity) {
stock -= quantity;
}
}
}
public class Order {
private String orderNumber;
private User user;
private List<OrderItem> items;
private OrderStatus status;
private Payment payment;
public void processPayment(PaymentMethod method) {
payment = new Payment(this, method);
payment.process();
}
public void ship() {
if (status == OrderStatus.PAID) {
status = OrderStatus.SHIPPED;
}
}
}
// 购物车类
public class ShoppingCart {
private Map<Product, Integer> items = new HashMap<>();
public void addItem(Product product, int quantity) {
items.merge(product, quantity, Integer::sum);
}
public BigDecimal getTotalPrice() {
return items.entrySet().stream()
.map(entry -> entry.getKey().getPrice().multiply(BigDecimal.valueOf(entry.getValue())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
电商系统架构表:
| 层次 | 类名 | 职责 | 关键方法 |
|---|---|---|---|
| 表示层 | UserController | 处理用户请求 | login(), register(), profile() |
| 业务层 | OrderService | 订单业务逻辑 | createOrder(), cancelOrder(), trackOrder() |
| 数据层 | ProductRepository | 数据访问 | findById(), save(), delete() |
| 模型层 | User, Product, Order | 业务实体 | 各种业务方法 |
5.2 银行金融系统
银行系统包含账户管理、交易处理、风险控制、客户服务等众多功能。面向对象编程可以帮助构建稳定、安全的金融系统,每个业务组件都可以作为独立的对象进行设计和实现。
银行系统核心类设计:
csharp
// 账户抽象基类
public abstract class Account {
protected string accountNumber;
protected decimal balance;
protected Customer owner;
protected DateTime createdDate;
public abstract void Deposit(decimal amount);
public abstract bool Withdraw(decimal amount);
public abstract decimal CalculateInterest();
public virtual string GetAccountInfo() {
return $"账户: {accountNumber}, 余额: {balance:C}, 户主: {owner.Name}";
}
}
// 储蓄账户
public class SavingsAccount : Account {
private decimal interestRate;
public SavingsAccount(string accountNumber, Customer owner, decimal initialBalance, decimal rate) {
this.accountNumber = accountNumber;
this.owner = owner;
this.balance = initialBalance;
this.interestRate = rate;
this.createdDate = DateTime.Now;
}
public override void Deposit(decimal amount) {
if (amount <= 0) throw new ArgumentException("存款金额必须大于0");
balance += amount;
Console.WriteLine($"存款成功,当前余额: {balance:C}");
}
public override bool Withdraw(decimal amount) {
if (amount <= 0 || amount > balance) {
Console.WriteLine("取款失败:金额无效或余额不足");
return false;
}
balance -= amount;
Console.WriteLine($"取款成功,当前余额: {balance:C}");
return true;
}
public override decimal CalculateInterest() {
return balance * interestRate;
}
}
// 交易类
public class Transaction {
public string TransactionId { get; private set; }
public Account SourceAccount { get; private set; }
public Account TargetAccount { get; private set; }
public decimal Amount { get; private set; }
public DateTime TransactionDate { get; private set; }
public TransactionType Type { get; private set; }
public Transaction(Account source, Account target, decimal amount, TransactionType type) {
TransactionId = Guid.NewGuid().ToString();
SourceAccount = source;
TargetAccount = target;
Amount = amount;
Type = type;
TransactionDate = DateTime.Now;
}
public void Execute() {
switch (Type) {
case TransactionType.Transfer:
if (SourceAccount.Withdraw(Amount)) {
TargetAccount.Deposit(Amount);
Console.WriteLine($"转账成功:{Amount:C} 从 {SourceAccount.accountNumber} 到 {TargetAccount.accountNumber}");
}
break;
case TransactionType.Deposit:
TargetAccount.Deposit(Amount);
break;
case TransactionType.Withdrawal:
SourceAccount.Withdraw(Amount);
break;
}
}
}
// 风险控制系统
public class RiskController {
private List<IRiskRule> rules = new List<IRiskRule>();
public RiskController() {
rules.Add(new LargeAmountRule());
rules.Add(new FrequentTransactionRule());
rules.Add(new UnusualLocationRule());
}
public RiskAssessment AssessRisk(Transaction transaction) {
RiskLevel riskLevel = RiskLevel.Low;
List<string> alerts = new List<string>();
foreach (var rule in rules) {
var result = rule.Evaluate(transaction);
if (result.RiskLevel > riskLevel) {
riskLevel = result.RiskLevel;
}
alerts.AddRange(result.Alerts);
}
return new RiskAssessment(riskLevel, alerts);
}
}
银行系统业务流程图:
客户开户 → 账户创建 → 风险评估 → 账户激活
↓
存款/取款 → 交易验证 → 风险检查 → 执行交易 → 记录日志
↓
转账操作 → 账户验证 → 余额检查 → 执行转账 → 通知客户
↓
月度结算 → 利息计算 → 账单生成 → 发送对账单
5.3 企业资源规划系统(ERP)
ERP系统整合了企业的人力资源、财务、供应链、生产等多个业务领域。面向对象设计可以有效地管理这些复杂的业务关系,提高系统的可维护性和可扩展性。
ERP系统模块设计:
python
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from typing import List, Dict, Optional
from enum import Enum
class EmployeeStatus(Enum):
ACTIVE = "在职"
INACTIVE = "离职"
ON_LEAVE = "请假"
class Department:
def __init__(self, dept_id: str, name: str, manager: 'Employee' = None):
self.dept_id = dept_id
self.name = name
self.manager = manager
self.employees: List['Employee'] = []
self.budget = 0.0
def add_employee(self, employee: 'Employee'):
if employee not in self.employees:
self.employees.append(employee)
employee.department = self
def calculate_total_salary(self) -> float:
return sum(emp.get_monthly_salary() for emp in self.employees if emp.status == EmployeeStatus.ACTIVE)
def get_headcount(self) -> int:
return len([emp for emp in self.employees if emp.status == EmployeeStatus.ACTIVE])
class Employee:
def __init__(self, emp_id: str, name: str, position: str, base_salary: float):
self.emp_id = emp_id
self.name = name
self.position = position
self.base_salary = base_salary
self.department: Optional[Department] = None
self.status = EmployeeStatus.ACTIVE
self.attendance: List['Attendance'] = []
self.performance_reviews: List['PerformanceReview'] = []
def get_monthly_salary(self) -> float:
bonus = self.calculate_performance_bonus()
return self.base_salary + bonus
def calculate_performance_bonus(self) -> float:
if not self.performance_reviews:
return 0.0
avg_score = sum(review.score for review in self.performance_reviews[-4:]) / min(4, len(self.performance_reviews))
return self.base_salary * 0.1 * (avg_score / 5.0) # 最高10%奖金
class Attendance:
def __init__(self, employee: Employee, date: datetime, check_in: datetime, check_out: Optional[datetime] = None):
self.employee = employee
self.date = date
self.check_in = check_in
self.check_out = check_out
self.hours_worked = 0.0
if check_out:
self.calculate_hours()
def calculate_hours(self):
if self.check_out:
diff = self.check_out - self.check_in
self.hours_worked = diff.total_seconds() / 3600
def is_overtime(self) -> bool:
return self.hours_worked > 8.0
class PurchaseOrder:
def __init__(self, po_id: str, supplier: 'Supplier', items: List['PurchaseItem']):
self.po_id = po_id
self.supplier = supplier
self.items = items
self.status = "待审批"
self.created_date = datetime.now()
self.approver: Optional[Employee] = None
self.approval_date: Optional[datetime] = None
def get_total_amount(self) -> float:
return sum(item.get_total_price() for item in self.items)
def approve(self, approver: Employee) -> bool:
if self.get_total_amount() > 10000 and approver.position not in ["采购经理", "财务总监"]:
return False
self.status = "已批准"
self.approver = approver
self.approval_date = datetime.now()
return True
class Inventory:
def __init__(self):
self.items: Dict[str, 'InventoryItem'] = {}
def add_item(self, item: 'InventoryItem'):
self.items[item.item_code] = item
def receive_purchase(self, purchase_order: PurchaseOrder):
for po_item in purchase_order.items:
if po_item.item_code in self.items:
self.items[po_item.item_code].add_quantity(po_item.quantity)
def check_stock_level(self, item_code: str) -> str:
if item_code not in self.items:
return "库存中无此商品"
item = self.items[item_code]
if item.quantity <= item.min_stock_level:
return f"库存不足,当前:{item.quantity},最小库存:{item.min_stock_level}"
elif item.quantity <= item.min_stock_level * 1.5:
return f"库存偏低,当前:{item.quantity}"
else:
return f"库存充足,当前:{item.quantity}"
# 生产计划管理
class ProductionOrder:
def __init__(self, order_id: str, product: 'Product', quantity: int, deadline: datetime):
self.order_id = order_id
self.product = product
self.quantity = quantity
self.deadline = deadline
self.status = "计划中"
self.assigned_resources: List['Resource'] = []
self.actual_start_date: Optional[datetime] = None
self.actual_end_date: Optional[datetime] = None
def calculate_production_time(self) -> float:
"""计算预计生产时间(小时)"""
unit_time = self.product.get_production_time()
total_time = unit_time * self.quantity
# 考虑资源效率
if self.assigned_resources:
avg_efficiency = sum(resource.efficiency for resource in self.assigned_resources) / len(self.assigned_resources)
total_time /= avg_efficiency
return total_time
def can_meet_deadline(self) -> bool:
"""检查是否能按时完成"""
production_time = self.calculate_production_time()
working_hours_per_day = 8
if self.actual_start_date:
completion_time = self.actual_start_date + timedelta(hours=production_time)
return completion_time <= self.deadline
else:
completion_time = datetime.now() + timedelta(hours=production_time)
return completion_time <= self.deadline
# ERP系统集成示例
class ERPSystem:
def __init__(self):
self.departments: Dict[str, Department] = {}
self.employees: Dict[str, Employee] = {}
self.inventory = Inventory()
self.purchase_orders: Dict[str, PurchaseOrder] = {}
self.production_orders: Dict[str, ProductionOrder] = {}
def generate_monthly_report(self, year: int, month: int) -> Dict:
"""生成月度综合报表"""
report = {
"period": f"{year}年{month}月",
"hr_metrics": self.get_hr_metrics(),
"inventory_status": self.get_inventory_status(),
"purchase_summary": self.get_purchase_summary(),
"production_status": self.get_production_status()
}
return report
def get_hr_metrics(self) -> Dict:
total_employees = len([emp for emp in self.employees.values() if emp.status == EmployeeStatus.ACTIVE])
total_payroll = sum(emp.get_monthly_salary() for emp in self.employees.values() if emp.status == EmployeeStatus.ACTIVE)
return {
"total_employees": total_employees,
"total_payroll": total_payroll,
"avg_salary": total_payroll / total_employees if total_employees > 0 else 0
}
ERP系统功能模块表:
| 模块 | 核心类 | 主要功能 | 业务流程 |
|---|---|---|---|
| 人力资源管理 | Employee, Department, Attendance | 员工管理、考勤、薪资计算 | 招聘→入职→考勤→薪资→离职 |
| 财务管理 | Invoice, Payment, Budget | 发票、付款、预算控制 | 预算制定→费用审批→付款→财务报表 |
| 供应链管理 | Supplier, PurchaseOrder, Inventory | 供应商管理、采购、库存 | 需求申请→采购审批→收货入库→库存管理 |
| 生产管理 | ProductionOrder, Product, Resource | 生产计划、资源调度、质量控制 | 生产计划→资源分配→执行→质量检验 |
总结
面向对象编程不仅仅是一种编程技术,更是一种思维方式和设计哲学。它通过将现实世界的事物抽象为程序中的对象,使得复杂的软件系统变得更加可控、可维护和可扩展。掌握面向对象编程的核心概念和设计原则,对于现代软件开发人员来说是必备的技能。在实际应用中,需要根据具体的业务需求和系统特点,灵活运用面向对象的思想和技术,构建出高质量的软件系统。