05、封装 -- 面向对象的特性

1、封装的概述 (封装(Encapsulation) – 如何隐藏信息、保护数据)

  • 封装 的具体实现:
    • 1、将属性数据 / 特征)和操作数据方法行为整合一个类中。
    • 2、隐藏内部实现细节,仅通过受控接口 (如:public 方法) 访问数据。
      • 用 private 修饰符,隐藏不愿意外部操作的 field方法构造器
      • 用 public 修饰符,暴露愿意外部调用的方法

  • 封装的核心:保护数据的 完整性安全性,防止外部直接修改或破坏数据。
    • 实现封装关键在于,绝对不能让其它类中的方法,直接访问这个类的实例字段
    • 程序只能通过对象方法与对象数据进行交互。
  • 封装为对象赋予了“黑盒”特征,这是提高重用性可靠性的关键。

  • 示例:
    • 4 个属性访问进行了限制
    • 调用者只允许通过中的 6 个方法访问修改钱包里的数据。
public class Wallet {
    /** 钱包的唯一编号 */
    private String id;
    /** 钱包创建的时间 */
    private long createTime;
    /** 钱包中的余额 */
    private BigDecimal balance;
    /** 上次钱包余额变更的时间 */
    private long balanceLastModifiedTime;

    // ... 省略其他属性...
    public Wallet() {
        this.id = IdGenerator.getInstance().generate();
        this.createTime = System.currentTimeMillis();
        this.balance = BigDecimal.ZERO;
        this.balanceLastModifiedTime = System.currentTimeMillis();
    }

    public String getId() {
        return this.id;
    }
    public long getCreateTime() {
        return this.createTime;
    }
    public BigDecimal getBalance() {
        return this.balance;
    }
    public long getBalanceLastModifiedTime() {
        return this.balanceLastModifiedTime;
    }

    public void increaseBalance(BigDecimal increasedAmount) {
        if (increasedAmount.compareTo(BigDecimal.ZERO) < 0) {
            throw new InvalidAmountException("...");
        }
        this.balance.add(increasedAmount);
        this.balanceLastModifiedTime = System.currentTimeMillis();
    }

    public void decreaseBalance(BigDecimal decreasedAmount) {
        if (decreasedAmount.compareTo(BigDecimal.ZERO) < 0) {
            throw new InvalidAmountException("...");
        }
        if (decreasedAmount.compareTo(this.balance) > 0) {
            throw new InsufficientAmountException("...");
        }
        this.balance.subtract(decreasedAmount);
        this.balanceLastModifiedTime = System.currentTimeMillis();
    }
}
  • 分析:
    • 业务的角度id、createTime创建钱包时就确定好了,之后不应该再被改动
      • Wallet 类中,未暴露 id、createTime 两个属性任何修改方法(如:set 方法 )。
    • 对于钱包余额 balance 这个属性,从业务的角度来说,只能,不会重新设置
      • Wallet 类中,只暴露 increaseBalancedecreaseBalance 方法,未暴露 set 方法
      • balanceLastModifiedTime 属性完全是跟 balance 属性修改操作绑定在一起 的。
        • 只有在 balance 修改时,balanceLastModifiedTime 属性才会被修改
        • 所以,把 balanceLastModifiedTime 属性修改操作完全封装increaseBalancedecreaseBalance 两个方法中,不对外暴露任何修改这个属性方法业务细节
      • 这样也保证了 balancebalanceLastModifiedTime 两个数据一致性

2、封装的级别

  • 1、封装。
  • 2、包级别封装:将具有共同特征的类放在同一个包下边。

3、封装的分类

  • 1、数据封装 :为了确保数据的完整性安全性成员变量形式呈现。
    • 1、将数据(属性)的具体存储细节隐藏(如:私有属性 private)。
    • 2、仅通过公开的方法(如:public 修饰的 getter/setter)提供对数据的受控访问
      • 如:检查输入数据的合法性。
public class BankAccount {
    // 数据抽象:隐藏 balance 的存储细节
    private double balance;

    // 提供受控的访问方法(数据操作)
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        }
    }

    public double getBalance() {
        return balance;
    }
}

// 使用
BankAccount account = new BankAccount();
account.deposit(1000);
account.withdraw(500);
System.out.println("余额: " + account.getBalance()); // 输出 500

  • 2、行为封装:以方法形式 呈现。
    • 将复杂操作的具体实现细节隐藏,仅暴露一个简单的接口(方法 或 函数)。
      • 隐藏方法的实现步骤(如:算法、流程)。
      • 通过方法名和参数定义功能,内部逻辑可自由修改。
      • 常用于模块化复杂逻辑(如:工具类方法)。
    • 方法内部逻辑还是用 面向过程思想实现的
    • 封装行为,调用者只需知道方法是“做什么的”,无需关心方法是“怎么实现的”。
      • 如:调用者只需调用 sort(),无需了解快速排序的具体实现。
      • 排序算法的内部细节被隐藏,未来可替换为其他算法 (如:归并排序),不影响调用方代码。
public class MathUtils {
    // 过程抽象:隐藏排序算法的具体实现
    public static void sort(int[] array) {
        // 使用快速排序(实现细节对调用者透明)
        quickSort(array, 0, array.length - 1);
    }

    private static void quickSort(int[] array, int low, int high) {
        if (low < high) {
            int pivot = partition(array, low, high);
            quickSort(array, low, pivot - 1);
            quickSort(array, pivot + 1, high);
        }
    }

    private static int partition(int[] array, int low, int high) {
        // 具体分区逻辑...
    }
}

// 使用
int[] numbers = {5, 3, 8, 1};
MathUtils.sort(numbers); // 调用者只需知道排序,无需关心实现

4、封装所需的支持

  • 封装特性,需要编程语言本身提供一定的语法机制来支持。这个语法机制就是访问权限控制
访问控制符(是否可以访问)本类中同包不同类(含无继承)不同包(有继承关系)不同包中(无继承关系)
private×××
默认(什么都不写××
proteted×
public

5、封装的优点

  • 1、增加复用
  • 2、单一职责,减少变动带来的风险。
  • 3、只能通过暴露方法来访问数据
  • 4、隐藏类的实例细节,增加安全性、方便修改和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值