Java面向对象详解

26 阅读15分钟

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关键字
│   └── 方法重写
│
├── 多态
│   ├── 向上转型
│   ├── 方法重写
│   └── 动态绑定
│
└── 抽象
    ├── 抽象类
    └── 接口