Java面向对象详解:核心概念与实战应用
前言
面向对象编程(Object-Oriented Programming,OOP)是Java语言的核心编程范式。掌握面向对象的思想和技术,是成为一名合格Java开发者的基础。本文将从面向对象的基本概念出发,结合实际项目和开源框架中的应用,全面讲解Java面向对象编程的核心知识点。
一、面向对象概述
1.1 什么是面向对象
面向对象是一种程序设计思想,它将现实世界中的事物抽象为对象,通过对象之间的交互来完成程序功能。
面向过程 vs 面向对象
┌─────────────────────────────────────────┐
│ 面向过程:关注"怎么做" │
│ - 以函数为基本单位 │
│ - 数据和操作分离 │
│ - 适合简单、线性的任务 │
├─────────────────────────────────────────┤
│ 面向对象:关注"谁来做" │
│ - 以对象为基本单位 │
│ - 数据和操作封装在一起 │
│ - 适合复杂、可扩展的系统 │
└─────────────────────────────────────────┘
1.2 面向对象的四大特性
┌─────────────────────────────────────┐
│ 面向对象四大特性 │
├─────────────────────────────────────┤
│ 1. 封装 (Encapsulation) │
│ 2. 继承 (Inheritance) │
│ 3. 多态 (Polymorphism) │
│ 4. 抽象 (Abstraction) │
└─────────────────────────────────────┘
二、类与对象
2.1 类的定义
类是对象的模板,定义了对象的属性和行为。
/**
* 用户类 - 类似于Spring Security中的User实体
*/
public class User {
// 属性(成员变量)
private Long id;
private String username;
private String password;
private String email;
private boolean enabled;
private LocalDateTime createTime;
// 无参构造方法
public User() {
}
// 有参构造方法
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
this.enabled = true;
this.createTime = LocalDateTime.now();
}
// 行为(方法)
public boolean isAccountValid() {
return enabled && username != null && !username.isEmpty();
}
public void disable() {
this.enabled = false;
}
// Getter和Setter方法
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
", enabled=" + enabled +
'}';
}
}
2.2 对象的创建与使用
public class UserDemo {
public static void main(String[] args) {
// 使用new关键字创建对象
User user1 = new User();
user1.setUsername("zhangsan");
user1.setPassword("123456");
user1.setEmail("zhangsan@example.com");
// 使用有参构造方法创建对象
User user2 = new User("lisi", "654321", "lisi@example.com");
// 调用对象的方法
System.out.println(user2.isAccountValid()); // true
user2.disable();
System.out.println(user2.isAccountValid()); // false
System.out.println(user1);
System.out.println(user2);
}
}
2.3 对象的内存结构
栈内存 (Stack) 堆内存 (Heap)
┌─────────────┐ ┌───────────────────────┐
│ user1 │────────>│ User对象 │
│ [0x1001] │ │ id: null │
├─────────────┤ │ username: "zhangsan" │
│ user2 │ │ password: "123456" │
│ [0x1002] │ │ email: "xxx@xxx" │
└─────────────┘ │ enabled: true │
└───────────────────────┘
┌───────────────────────┐
────────>│ User对象 │
│ id: null │
│ username: "lisi" │
│ ... │
└───────────────────────┘
三、封装
3.1 封装的概念
封装是将对象的状态(属性)和行为(方法)包装在一起,隐藏内部实现细节,只对外提供公共的访问方式。
3.2 访问修饰符
┌──────────────┬───────┬──────────┬─────────┬─────────┐
│ 修饰符 │ 类内部 │ 同一包内 │ 子类 │ 其他包 │
├──────────────┼───────┼──────────┼─────────┼─────────┤
│ private │ ✓ │ ✗ │ ✗ │ ✗ │
│ default │ ✓ │ ✓ │ ✗ │ ✗ │
│ protected │ ✓ │ ✓ │ ✓ │ ✗ │
│ public │ ✓ │ ✓ │ ✓ │ ✓ │
└──────────────┴───────┴──────────┴─────────┴─────────┘
3.3 封装实践
/**
* 银行账户类 - 演示封装的重要性
*/
public class BankAccount {
// 私有属性,外部无法直接访问
private String accountNumber;
private String ownerName;
private double balance;
private List<String> transactionHistory;
public BankAccount(String accountNumber, String ownerName) {
this.accountNumber = accountNumber;
this.ownerName = ownerName;
this.balance = 0.0;
this.transactionHistory = new ArrayList<>();
}
// 公共方法提供受控的访问
public void deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("存款金额必须大于0");
}
this.balance += amount;
addTransaction("存款: +" + amount);
}
public void withdraw(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("取款金额必须大于0");
}
if (amount > balance) {
throw new IllegalStateException("余额不足");
}
this.balance -= amount;
addTransaction("取款: -" + amount);
}
public boolean transfer(BankAccount target, double amount) {
if (target == null) {
throw new IllegalArgumentException("目标账户不能为空");
}
try {
this.withdraw(amount);
target.deposit(amount);
addTransaction("转账至" + target.accountNumber + ": -" + amount);
return true;
} catch (Exception e) {
return false;
}
}
// 只读访问
public double getBalance() {
return balance;
}
public String getAccountNumber() {
return accountNumber;
}
// 返回交易历史的副本,防止外部修改
public List<String> getTransactionHistory() {
return new ArrayList<>(transactionHistory);
}
private void addTransaction(String record) {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
transactionHistory.add(timestamp + " " + record);
}
}
/**
* 使用示例
*/
class BankAccountDemo {
public static void main(String[] args) {
BankAccount account1 = new BankAccount("6222001234", "张三");
BankAccount account2 = new BankAccount("6222005678", "李四");
// 通过公共方法操作账户
account1.deposit(10000);
account1.withdraw(2000);
account1.transfer(account2, 3000);
System.out.println("账户1余额: " + account1.getBalance()); // 5000
System.out.println("账户2余额: " + account2.getBalance()); // 3000
// 无法直接修改余额
// account1.balance = 1000000; // 编译错误!
// 查看交易历史
account1.getTransactionHistory().forEach(System.out::println);
}
}
3.4 JavaBean规范
/**
* 标准的JavaBean类
* 类似于Spring框架中的实体类
*/
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private BigDecimal price;
private Integer stock;
private String description;
private boolean available;
// 无参构造方法
public Product() {
}
// Getter和Setter遵循命名规范
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
// boolean类型使用is前缀
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
}
四、继承
4.1 继承的概念
继承是面向对象的重要特性,子类可以继承父类的属性和方法,实现代码复用。
/**
* 父类:员工基类
*/
public class Employee {
protected Long id;
protected String name;
protected String department;
protected double baseSalary;
protected LocalDate hireDate;
public Employee(String name, String department, double baseSalary) {
this.name = name;
this.department = department;
this.baseSalary = baseSalary;
this.hireDate = LocalDate.now();
}
// 计算工资的方法(子类可以重写)
public double calculateSalary() {
return baseSalary;
}
public void work() {
System.out.println(name + "正在工作...");
}
public int getWorkYears() {
return LocalDate.now().getYear() - hireDate.getYear();
}
// Getter和Setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getBaseSalary() { return baseSalary; }
public void setBaseSalary(double baseSalary) { this.baseSalary = baseSalary; }
}
/**
* 子类:程序员
*/
public class Programmer extends Employee {
private String programmingLanguage;
private int bugCount;
public Programmer(String name, String department, double baseSalary, String language) {
// 调用父类构造方法
super(name, department, baseSalary);
this.programmingLanguage = language;
this.bugCount = 0;
}
// 重写父类方法
@Override
public double calculateSalary() {
// 程序员有绩效奖金
double bonus = baseSalary * 0.2;
// 每个bug扣50元
double deduction = bugCount * 50;
return baseSalary + bonus - deduction;
}
@Override
public void work() {
System.out.println(name + "正在用" + programmingLanguage + "编写代码...");
}
// 子类特有方法
public void fixBug() {
if (bugCount > 0) {
bugCount--;
System.out.println(name + "修复了一个bug,剩余: " + bugCount);
}
}
public void createBug() {
bugCount++;
System.out.println(name + "产生了一个bug,当前: " + bugCount);
}
public String getProgrammingLanguage() { return programmingLanguage; }
}
/**
* 子类:经理
*/
public class Manager extends Employee {
private List<Employee> team;
private double bonusRate;
public Manager(String name, String department, double baseSalary) {
super(name, department, baseSalary);
this.team = new ArrayList<>();
this.bonusRate = 0.3;
}
@Override
public double calculateSalary() {
// 经理的奖金与团队规模相关
double teamBonus = team.size() * 500;
return baseSalary * (1 + bonusRate) + teamBonus;
}
@Override
public void work() {
System.out.println(name + "正在管理团队和开会...");
}
public void addTeamMember(Employee employee) {
team.add(employee);
System.out.println(employee.getName() + "加入了" + name + "的团队");
}
public List<Employee> getTeam() {
return new ArrayList<>(team);
}
}
4.2 继承的使用
public class InheritanceDemo {
public static void main(String[] args) {
// 创建不同类型的员工
Programmer programmer = new Programmer("张三", "技术部", 15000, "Java");
Manager manager = new Manager("李四", "技术部", 25000);
// 程序员工作
programmer.work();
programmer.createBug();
programmer.createBug();
programmer.fixBug();
// 经理工作
manager.work();
manager.addTeamMember(programmer);
// 计算工资
System.out.println("程序员工资: " + programmer.calculateSalary());
System.out.println("经理工资: " + manager.calculateSalary());
// 调用继承的方法
System.out.println("程序员工作年限: " + programmer.getWorkYears());
}
}
4.3 继承层次结构
Employee
│
┌─────────┼─────────┐
│ │ │
Programmer Manager Designer
│
│
SeniorProgrammer
4.4 super关键字
/**
* 高级程序员 - 演示super关键字的使用
*/
public class SeniorProgrammer extends Programmer {
private String title;
private double seniorBonus;
public SeniorProgrammer(String name, String department, double baseSalary, String language) {
// super调用父类构造方法
super(name, department, baseSalary, language);
this.title = "高级工程师";
this.seniorBonus = 5000;
}
@Override
public double calculateSalary() {
// super调用父类方法
return super.calculateSalary() + seniorBonus;
}
@Override
public void work() {
super.work(); // 调用父类的work方法
System.out.println(name + "还在进行代码评审和技术指导...");
}
public void mentor(Programmer junior) {
System.out.println(title + " " + name + "正在指导" + junior.getName());
}
}
4.5 方法重写规则
/**
* 方法重写规则演示
*/
public class OverrideRules {
static class Parent {
public void publicMethod() { }
protected void protectedMethod() { }
void defaultMethod() { }
private void privateMethod() { } // 私有方法不能被重写
public Number getValue() { return 0; }
public void process() throws IOException { }
}
static class Child extends Parent {
// 1. 访问权限可以扩大,不能缩小
@Override
public void publicMethod() { } // ✓ 相同权限
@Override
public void protectedMethod() { } // ✓ 扩大为public
@Override
public void defaultMethod() { } // ✓ 扩大为public
// 2. 返回类型可以是父类方法返回类型的子类(协变返回)
@Override
public Integer getValue() { return 0; } // ✓ Integer是Number的子类
// 3. 抛出的异常可以更少或更具体,不能更多或更宽泛
@Override
public void process() throws FileNotFoundException { } // ✓ 更具体的异常
}
}
五、多态
5.1 多态的概念
多态是指同一个行为具有多个不同的表现形式,是面向对象最强大的特性之一。
/**
* 多态示例:支付系统
* 类似于支付宝、微信等支付平台的设计
*/
public abstract class Payment {
protected String orderId;
protected double amount;
public Payment(String orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
}
// 抽象方法,子类必须实现
public abstract boolean pay();
public abstract String getPaymentMethod();
// 通用方法
public void printReceipt() {
System.out.println("========== 支付凭证 ==========");
System.out.println("订单号: " + orderId);
System.out.println("支付方式: " + getPaymentMethod());
System.out.println("支付金额: " + amount + "元");
System.out.println("==============================");
}
}
/**
* 支付宝支付
*/
public class AlipayPayment extends Payment {
private String alipayAccount;
public AlipayPayment(String orderId, double amount, String alipayAccount) {
super(orderId, amount);
this.alipayAccount = alipayAccount;
}
@Override
public boolean pay() {
System.out.println("正在通过支付宝账户[" + alipayAccount + "]支付...");
// 模拟支付逻辑
System.out.println("支付宝支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return "支付宝";
}
}
/**
* 微信支付
*/
public class WechatPayment extends Payment {
private String openId;
public WechatPayment(String orderId, double amount, String openId) {
super(orderId, amount);
this.openId = openId;
}
@Override
public boolean pay() {
System.out.println("正在通过微信[" + openId + "]支付...");
System.out.println("微信支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return "微信支付";
}
}
/**
* 银行卡支付
*/
public class BankCardPayment extends Payment {
private String cardNumber;
private String bankName;
public BankCardPayment(String orderId, double amount, String cardNumber, String bankName) {
super(orderId, amount);
this.cardNumber = cardNumber;
this.bankName = bankName;
}
@Override
public boolean pay() {
String maskedCard = "****" + cardNumber.substring(cardNumber.length() - 4);
System.out.println("正在通过" + bankName + "银行卡[" + maskedCard + "]支付...");
System.out.println("银行卡支付成功!");
return true;
}
@Override
public String getPaymentMethod() {
return bankName + "银行卡";
}
}
5.2 多态的使用
/**
* 订单服务 - 演示多态的应用
*/
public class OrderService {
/**
* 处理订单支付 - 使用多态
* 无需关心具体的支付方式
*/
public boolean processPayment(Payment payment) {
System.out.println("开始处理支付...");
// 多态:调用的是实际对象的方法
boolean success = payment.pay();
if (success) {
payment.printReceipt();
updateOrderStatus(payment.orderId, "已支付");
} else {
updateOrderStatus(payment.orderId, "支付失败");
}
return success;
}
private void updateOrderStatus(String orderId, String status) {
System.out.println("订单[" + orderId + "]状态更新为: " + status);
}
}
/**
* 多态使用示例
*/
class PolymorphismDemo {
public static void main(String[] args) {
OrderService orderService = new OrderService();
// 父类引用指向子类对象
Payment payment1 = new AlipayPayment("ORD001", 99.9, "zhangsan@alipay.com");
Payment payment2 = new WechatPayment("ORD002", 199.0, "wx_openid_123");
Payment payment3 = new BankCardPayment("ORD003", 599.0, "6222021234567890", "工商");
// 多态调用 - 同一个方法,不同的行为
orderService.processPayment(payment1);
System.out.println();
orderService.processPayment(payment2);
System.out.println();
orderService.processPayment(payment3);
// 批量处理
List<Payment> payments = Arrays.asList(payment1, payment2, payment3);
for (Payment payment : payments) {
System.out.println("支付方式: " + payment.getPaymentMethod());
}
}
}
5.3 向上转型与向下转型
public class CastingDemo {
public static void main(String[] args) {
// 向上转型(自动)
Payment payment = new AlipayPayment("ORD001", 100, "test@alipay.com");
// payment只能访问Payment类中定义的方法
// 向下转型(需要强制转换)
if (payment instanceof AlipayPayment) {
AlipayPayment alipay = (AlipayPayment) payment;
// 现在可以访问AlipayPayment特有的方法
}
// Java 16+ 模式匹配
if (payment instanceof AlipayPayment alipay) {
// 直接使用alipay
System.out.println("这是支付宝支付");
}
// instanceof检查
System.out.println(payment instanceof Payment); // true
System.out.println(payment instanceof AlipayPayment); // true
System.out.println(payment instanceof WechatPayment); // false
}
}
5.4 多态的实现原理
编译时类型 vs 运行时类型
┌─────────────────────────────────────────┐
│ Payment payment = new AlipayPayment(); │
│ ↓ ↓ │
│ 编译时类型 运行时类型 │
│ │
│ 编译器检查:Payment中是否有pay()方法 │
│ 运行时执行:AlipayPayment的pay()方法 │
└─────────────────────────────────────────┘
六、抽象
6.1 抽象类
/**
* 抽象类:数据库连接池
* 类似于Apache Commons DBCP的设计
*/
public abstract class AbstractConnectionPool {
protected String url;
protected String username;
protected String password;
protected int maxSize;
protected int minSize;
protected List<Connection> availableConnections;
protected List<Connection> usedConnections;
public AbstractConnectionPool(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
this.maxSize = 10;
this.minSize = 2;
this.availableConnections = new ArrayList<>();
this.usedConnections = new ArrayList<>();
}
// 抽象方法 - 子类必须实现
protected abstract Connection createConnection() throws SQLException;
protected abstract boolean validateConnection(Connection connection);
// 具体方法 - 通用逻辑
public synchronized Connection getConnection() throws SQLException {
if (availableConnections.isEmpty()) {
if (usedConnections.size() < maxSize) {
Connection conn = createConnection();
usedConnections.add(conn);
return conn;
} else {
throw new SQLException("连接池已满");
}
}
Connection connection = availableConnections.remove(availableConnections.size() - 1);
if (!validateConnection(connection)) {
connection = createConnection();
}
usedConnections.add(connection);
return connection;
}
public synchronized void releaseConnection(Connection connection) {
usedConnections.remove(connection);
if (availableConnections.size() < maxSize) {
availableConnections.add(connection);
} else {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public int getAvailableCount() {
return availableConnections.size();
}
public int getUsedCount() {
return usedConnections.size();
}
}
/**
* MySQL连接池实现
*/
public class MySQLConnectionPool extends AbstractConnectionPool {
public MySQLConnectionPool(String url, String username, String password) {
super(url, username, password);
}
@Override
protected Connection createConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
@Override
protected boolean validateConnection(Connection connection) {
try {
return connection != null && !connection.isClosed() && connection.isValid(1);
} catch (SQLException e) {
return false;
}
}
}
6.2 接口
/**
* 接口:缓存服务
* 类似于Spring Cache的设计
*/
public interface CacheService {
// 常量(默认public static final)
int DEFAULT_EXPIRE_TIME = 3600;
// 抽象方法
void put(String key, Object value);
void put(String key, Object value, int expireSeconds);
Object get(String key);
void remove(String key);
boolean exists(String key);
void clear();
// 默认方法(Java 8+)
default void putIfAbsent(String key, Object value) {
if (!exists(key)) {
put(key, value);
}
}
// 静态方法(Java 8+)
static String generateKey(String prefix, String... parts) {
return prefix + ":" + String.join(":", parts);
}
}
/**
* 内存缓存实现
*/
public class MemoryCacheService implements CacheService {
private Map<String, CacheItem> cache = new ConcurrentHashMap<>();
private static class CacheItem {
Object value;
long expireTime;
CacheItem(Object value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}
boolean isExpired() {
return expireTime > 0 && System.currentTimeMillis() > expireTime;
}
}
@Override
public void put(String key, Object value) {
put(key, value, DEFAULT_EXPIRE_TIME);
}
@Override
public void put(String key, Object value, int expireSeconds) {
long expireTime = expireSeconds > 0
? System.currentTimeMillis() + expireSeconds * 1000L
: 0;
cache.put(key, new CacheItem(value, expireTime));
}
@Override
public Object get(String key) {
CacheItem item = cache.get(key);
if (item == null || item.isExpired()) {
cache.remove(key);
return null;
}
return item.value;
}
@Override
public void remove(String key) {
cache.remove(key);
}
@Override
public boolean exists(String key) {
CacheItem item = cache.get(key);
if (item != null && item.isExpired()) {
cache.remove(key);
return false;
}
return item != null;
}
@Override
public void clear() {
cache.clear();
}
}
/**
* Redis缓存实现(简化版)
*/
public class RedisCacheService implements CacheService {
private Map<String, Object> redisSimulator = new ConcurrentHashMap<>();
@Override
public void put(String key, Object value) {
redisSimulator.put(key, value);
System.out.println("Redis SET " + key);
}
@Override
public void put(String key, Object value, int expireSeconds) {
redisSimulator.put(key, value);
System.out.println("Redis SETEX " + key + " " + expireSeconds);
}
@Override
public Object get(String key) {
System.out.println("Redis GET " + key);
return redisSimulator.get(key);
}
@Override
public void remove(String key) {
redisSimulator.remove(key);
System.out.println("Redis DEL " + key);
}
@Override
public boolean exists(String key) {
return redisSimulator.containsKey(key);
}
@Override
public void clear() {
redisSimulator.clear();
System.out.println("Redis FLUSHDB");
}
}
6.3 抽象类与接口的选择
┌────────────────────┬─────────────────────┬─────────────────────┐
│ 特性 │ 抽象类 │ 接口 │
├────────────────────┼─────────────────────┼─────────────────────┤
│ 方法实现 │ 可以有 │ 默认方法/静态方法 │
│ 成员变量 │ 可以有 │ 只能是常量 │
│ 构造方法 │ 可以有 │ 没有 │
│ 继承 │ 单继承 │ 多实现 │
│ 关系 │ is-a │ can-do / like-a │
│ 设计目的 │ 代码复用 │ 定义契约 │
└────────────────────┴─────────────────────┴─────────────────────┘
选择建议:
- 如果需要共享代码 → 抽象类
- 如果需要多重继承 → 接口
- 如果要定义行为契约 → 接口
- 如果有共同的属性和方法 → 抽象类
七、设计原则与模式
7.1 SOLID原则
/**
* S - 单一职责原则 (Single Responsibility Principle)
*/
// ❌ 违反单一职责
class UserServiceBad {
public void createUser(User user) { }
public void sendEmail(String email, String content) { } // 不应该在这里
public void generateReport() { } // 不应该在这里
}
// ✓ 遵循单一职责
class UserService {
public void createUser(User user) { }
public User findById(Long id) { return null; }
}
class EmailService {
public void sendEmail(String email, String content) { }
}
class ReportService {
public void generateReport() { }
}
/**
* O - 开闭原则 (Open/Closed Principle)
*/
// ✓ 对扩展开放,对修改关闭
interface DiscountStrategy {
double calculateDiscount(double price);
}
class NormalDiscount implements DiscountStrategy {
public double calculateDiscount(double price) {
return price * 0.95;
}
}
class VIPDiscount implements DiscountStrategy {
public double calculateDiscount(double price) {
return price * 0.8;
}
}
// 添加新的折扣策略无需修改现有代码
class NewYearDiscount implements DiscountStrategy {
public double calculateDiscount(double price) {
return price * 0.7;
}
}
/**
* L - 里氏替换原则 (Liskov Substitution Principle)
*/
// 子类必须能够替换父类
class Rectangle {
protected int width;
protected int height;
public void setWidth(int width) { this.width = width; }
public void setHeight(int height) { this.height = height; }
public int getArea() { return width * height; }
}
// ❌ 违反里氏替换原则
class SquareBad extends Rectangle {
@Override
public void setWidth(int width) {
this.width = width;
this.height = width; // 破坏了父类的行为
}
}
/**
* I - 接口隔离原则 (Interface Segregation Principle)
*/
// ❌ 臃肿的接口
interface WorkerBad {
void work();
void eat();
void sleep();
}
// ✓ 隔离的接口
interface Workable {
void work();
}
interface Eatable {
void eat();
}
interface Sleepable {
void sleep();
}
class HumanWorker implements Workable, Eatable, Sleepable {
public void work() { }
public void eat() { }
public void sleep() { }
}
class RobotWorker implements Workable {
public void work() { } // 机器人不需要吃饭睡觉
}
/**
* D - 依赖倒置原则 (Dependency Inversion Principle)
*/
// ❌ 依赖具体实现
class OrderServiceBad {
private MySQLOrderRepository repository = new MySQLOrderRepository();
}
// ✓ 依赖抽象
interface OrderRepository {
void save(Order order);
}
class OrderServiceGood {
private OrderRepository repository;
// 通过构造函数注入依赖
public OrderServiceGood(OrderRepository repository) {
this.repository = repository;
}
}
7.2 常用设计模式示例
工厂模式
/**
* 工厂模式:消息发送器
*/
interface MessageSender {
void send(String message, String target);
}
class EmailSender implements MessageSender {
@Override
public void send(String message, String target) {
System.out.println("发送邮件到 " + target + ": " + message);
}
}
class SmsSender implements MessageSender {
@Override
public void send(String message, String target) {
System.out.println("发送短信到 " + target + ": " + message);
}
}
class PushSender implements MessageSender {
@Override
public void send(String message, String target) {
System.out.println("推送消息到 " + target + ": " + message);
}
}
/**
* 简单工厂
*/
class MessageSenderFactory {
public static MessageSender create(String type) {
switch (type.toLowerCase()) {
case "email":
return new EmailSender();
case "sms":
return new SmsSender();
case "push":
return new PushSender();
default:
throw new IllegalArgumentException("未知的消息类型: " + type);
}
}
}
// 使用
class FactoryDemo {
public static void main(String[] args) {
MessageSender sender = MessageSenderFactory.create("email");
sender.send("Hello", "test@example.com");
}
}
模板方法模式
/**
* 模板方法模式:数据导出
* 类似于Spring JdbcTemplate的设计
*/
public abstract class DataExporter {
// 模板方法 - 定义算法骨架
public final void export(String fileName) {
List<Map<String, Object>> data = fetchData();
String content = formatData(data);
writeToFile(fileName, content);
afterExport(fileName);
}
// 抽象方法 - 子类实现
protected abstract List<Map<String, Object>> fetchData();
protected abstract String formatData(List<Map<String, Object>> data);
// 钩子方法 - 子类可选择重写
protected void afterExport(String fileName) {
System.out.println("导出完成: " + fileName);
}
// 具体方法 - 通用实现
private void writeToFile(String fileName, String content) {
System.out.println("写入文件: " + fileName);
// 实际的文件写入逻辑
}
}
/**
* CSV导出实现
*/
class CsvExporter extends DataExporter {
@Override
protected List<Map<String, Object>> fetchData() {
// 从数据库获取数据
return new ArrayList<>();
}
@Override
protected String formatData(List<Map<String, Object>> data) {
StringBuilder sb = new StringBuilder();
// 格式化为CSV
for (Map<String, Object> row : data) {
sb.append(String.join(",", row.values().stream()
.map(Object::toString).toArray(String[]::new)));
sb.append("\n");
}
return sb.toString();
}
}
/**
* JSON导出实现
*/
class JsonExporter extends DataExporter {
@Override
protected List<Map<String, Object>> fetchData() {
return new ArrayList<>();
}
@Override
protected String formatData(List<Map<String, Object>> data) {
// 格式化为JSON
return data.toString();
}
@Override
protected void afterExport(String fileName) {
super.afterExport(fileName);
System.out.println("JSON文件可以被前端直接使用");
}
}
八、实战案例:构建一个简单的Web框架
/**
* 简化版的Web框架设计
* 展示面向对象在实际框架中的应用
*/
// 1. 请求和响应的封装
public class HttpRequest {
private String method;
private String path;
private Map<String, String> parameters;
private Map<String, String> headers;
public HttpRequest(String method, String path) {
this.method = method;
this.path = path;
this.parameters = new HashMap<>();
this.headers = new HashMap<>();
}
public String getMethod() { return method; }
public String getPath() { return path; }
public String getParameter(String name) { return parameters.get(name); }
public void setParameter(String name, String value) { parameters.put(name, value); }
public String getHeader(String name) { return headers.get(name); }
public void setHeader(String name, String value) { headers.put(name, value); }
}
public class HttpResponse {
private int statusCode;
private String contentType;
private String body;
public HttpResponse() {
this.statusCode = 200;
this.contentType = "text/html";
}
public void setStatus(int code) { this.statusCode = code; }
public void setContentType(String type) { this.contentType = type; }
public void setBody(String body) { this.body = body; }
public void json(Object data) {
this.contentType = "application/json";
this.body = data.toString(); // 实际应使用JSON库
}
@Override
public String toString() {
return "HTTP/1.1 " + statusCode + "\n" +
"Content-Type: " + contentType + "\n\n" +
body;
}
}
// 2. 控制器接口
public interface Controller {
void handle(HttpRequest request, HttpResponse response);
}
// 3. 具体的控制器
public class UserController implements Controller {
@Override
public void handle(HttpRequest request, HttpResponse response) {
String userId = request.getParameter("id");
if (userId != null) {
response.json("{'id': " + userId + ", 'name': 'User" + userId + "'}");
} else {
response.setStatus(400);
response.setBody("Missing user id");
}
}
}
public class HomeController implements Controller {
@Override
public void handle(HttpRequest request, HttpResponse response) {
response.setBody("<h1>Welcome to Simple Web Framework</h1>");
}
}
// 4. 路由器
public class Router {
private Map<String, Controller> routes = new HashMap<>();
public void addRoute(String path, Controller controller) {
routes.put(path, controller);
}
public Controller getController(String path) {
return routes.get(path);
}
}
// 5. 应用程序
public class Application {
private Router router;
private List<Filter> filters;
public Application() {
this.router = new Router();
this.filters = new ArrayList<>();
}
public void route(String path, Controller controller) {
router.addRoute(path, controller);
}
public void addFilter(Filter filter) {
filters.add(filter);
}
public HttpResponse handleRequest(HttpRequest request) {
HttpResponse response = new HttpResponse();
// 执行过滤器
for (Filter filter : filters) {
if (!filter.doFilter(request, response)) {
return response;
}
}
// 路由到控制器
Controller controller = router.getController(request.getPath());
if (controller != null) {
controller.handle(request, response);
} else {
response.setStatus(404);
response.setBody("Not Found");
}
return response;
}
}
// 6. 过滤器接口
public interface Filter {
boolean doFilter(HttpRequest request, HttpResponse response);
}
// 7. 日志过滤器
public class LoggingFilter implements Filter {
@Override
public boolean doFilter(HttpRequest request, HttpResponse response) {
System.out.println("[" + LocalDateTime.now() + "] " +
request.getMethod() + " " + request.getPath());
return true;
}
}
// 8. 使用示例
class WebFrameworkDemo {
public static void main(String[] args) {
Application app = new Application();
// 注册路由
app.route("/", new HomeController());
app.route("/user", new UserController());
// 添加过滤器
app.addFilter(new LoggingFilter());
// 模拟请求
HttpRequest request1 = new HttpRequest("GET", "/");
System.out.println(app.handleRequest(request1));
HttpRequest request2 = new HttpRequest("GET", "/user");
request2.setParameter("id", "123");
System.out.println(app.handleRequest(request2));
HttpRequest request3 = new HttpRequest("GET", "/unknown");
System.out.println(app.handleRequest(request3));
}
}
九、总结
核心知识点回顾
Java面向对象核心要点
│
├── 类与对象
│ ├── 类是对象的模板
│ └── 对象是类的实例
│
├── 封装
│ ├── 隐藏内部实现
│ ├── 访问修饰符
│ └── Getter/Setter
│
├── 继承
│ ├── extends关键字
│ ├── super关键字
│ └── 方法重写
│
├── 多态
│ ├── 向上转型
│ ├── 方法重写
│ └── 动态绑定
│
└── 抽象
├── 抽象类
└── 接口