简单易懂读《重构》 - Inappropriate Intimacy(不合适的亲昵关系)

重构不合适的亲昵关系
本文探讨了软件设计中类间过度依赖的问题,即“不合适的亲昵关系”,并介绍了几种重构方法,如搬移函数、搬移字段、将双向关联改为单向关联等,以降低代码耦合度,提升类的独立性和系统的可维护性。

不合适的亲昵关系

  • 含义:
    两个类间互相依赖,总是调用对方的过多属性。
  • 坏处:
    代码耦合度高,破坏类的独立性
  • 目标:
    把联系过分紧密部分搬移或者建立新类放在其中。
  • 实现方法:
    • 使用Move Method(搬移函数)Move Field(搬移字段) 来使字段或函数放在正确的位置,避免2个类之间过多的交互。
    • 也可以尝试使用 Change Bidirectional Association to Unidirectional (将双向关联改为单向关联) 来减少耦合。
    • 如果两个类实在分离不开,使用 Extract Class(提炼类) 把两者合并到一块。也可以尝试 Hide Delegate(隐藏委托关系) 把互相之间的访问委托给第三方来斩断直接的访问。
    • 如果是继承关系,子类不需要父类中过多的内容,运用 Replace Inheritance with Delegation(用委托代替继承) 来处理不恰当的继承关系。

本文涉及的重构方法

Move Method(搬移函数)
Move Field(搬移字段)
Change Bidirectional Association to Unidirectional (将双向关联改为单向关联)
  • 作用:
    使两个互相依赖的类断开不必要的依赖
  • 重构思路:
    重构前考虑断开依赖是否会造成复杂性过高。在考虑是否使用。以入参的方法减少直接的依赖关系。
Extract Class(提炼类)
Hide Delegate(隐藏委托关系)
Replace Inheritance with Delegation(用委托代替继承)
在 Android 开发中,使用 SQLite 数据库时可能会遇到 `OS error - 25: Inappropriate ioctl for device` 错误,并伴随 `SQLiteDatabaseLockedException`。这一问题通常与数据库文件的访问权限、并发操作或底层 I/O 操作异常有关。 ### 1. 文件系统权限与设备兼容性 该错误信息中的 `-25: Inappropriate ioctl for device` 表明在尝试对数据库文件执行某些底层 I/O 控制操作时,操作系统认为该操作适用于当前设备或文件类型。这可能发生在非标准文件系统上运行 SQLite 或数据库文件被放置在具备完整 POSIX 文件系统语义的存储位置(如某些内存映射或临时文件系统)时[^4]。 应确保数据库文件存储在具备完整文件系统支持的路径中,例如应用私有目录: ```java Context context = getApplicationContext(); File dbFile = context.getDatabasePath("your_database_name.db"); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); ``` ### 2. 并发访问控制与线程安全 SQLite 在多线程环境下默认并非完全线程安全。当多个线程同时尝试写入或取数据库而未正确同步时,可能导致数据库锁定并触发此错误。为避免此类问题,建议采用单例模式管理数据库连接,并确保所有线程通过同一实例访问数据库[^1]。 示例代码如下: ```java public class DatabaseManager { private static volatile DatabaseManager instance; private SQLiteDatabase database; private DatabaseHelper helper; private DatabaseManager(Context context) { helper = new DatabaseHelper(context); database = helper.getWritableDatabase(); } public static DatabaseManager getInstance(Context context) { if (instance == null) { synchronized (DatabaseManager.class) { if (instance == null) { instance = new DatabaseManager(context); } } } return instance; } public SQLiteDatabase getDatabase() { return database; } } ``` ### 3. 正确处理事务和资源释放 未正确结束事务或关闭数据库连接也可能导致资源无法释放,从而引发锁定问题。在执行批量插入或更新操作时,应始终使用事务并确保调用 `setTransactionSuccessful()` 和 `endTransaction()`: ```java SQLiteDatabase db = DatabaseManager.getInstance(context).getDatabase(); db.beginTransaction(); try { // 执行多个数据库操作 db.setTransactionSuccessful(); } finally { db.endTransaction(); } ``` 此外,在每次操作完成后应确保调用 `close()` 方法以释放数据库连接资源: ```java try (SQLiteDatabase db = helper.getWritableDatabase()) { // 执行数据库操作 } catch (Exception e) { // 异常处理 } ``` ### 4. 使用 WAL 模式提升并发性能 SQLite 的 Write-Ahead Logging (WAL) 模式可以显著提升多线程环境下的并发性能。启用 WAL 模式可减少数据库锁定的发生频率: ```java db.enableWriteAheadLogging(); ``` 或者在打开数据库后手动执行 PRAGMA 命令: ```java db.execSQL("PRAGMA journal_mode = WAL;"); ``` ### 5. 避免调试过程中打断数据库流程 在调试器中设置断点特别是在数据库连接和事务执行期间,可能导致资源未正常释放,进而引发锁定异常。应尽量避免在此类关键路径中打断程序执行流程[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值