在这一章中作者像我们交代了对外部API(Application Programming Interface)的重构,旨在确保代码对外部的依赖关系和接口设计既清晰又简洁,笔记如下:
以函数对象取代函数(Replace Function with Function Pointer):问题: 在API中传递函数时,直接使用函数指针(或函数对象)。解决方法: 将函数封装成对象,通常是实现了特定接口的类,然后传递对象而非直接传递函数。
// Beforevoid processFunction(void (*func)(int)) {// Function logic here}// Aftervoid processFunction(FunctionObject funcObject) {// Function logic using funcObject}
以命令取代函数(Replace Function with Command):
问题: 在API中传递的函数逻辑过于简单,难以方便地进行扩展。
解决方法: 将函数封装成一个命令对象,以更灵活地扩展和组合不同的逻辑。
// Beforevoid processFunction(Function func) {// Function logic here}// Aftervoid processCommand(Command command) {command.execute();}
以函数取代命令(Replace Command with Function):
问题: 使用命令对象的开销较大,逻辑相对简单。
解决方法: 将命令对象替换为函数,以简化代码结构。
// Beforeclass Command {void execute() {// Command logic here}}// Aftervoid processFunction(Function func) {// Function logic here}
以明确的函数取代参数方法(Replace Parameter with Explicit Methods):
问题: 使用一个参数控制函数的行为,而这个参数可能有多个取值。
解决方法: 将带有参数的函数替换为多个明确的函数,每个函数对应一个可能的参数值。
// Beforevoid process(int type) {// Process based on type}// Aftervoid processTypeA() {// Process for type A}void processTypeB() {// Process for type B}
以工厂函数取代构造函数(Replace Constructor with Factory Method):
问题: 直接使用构造函数创建对象,但可能需要更多的灵活性。
解决方法: 使用工厂函数创建对象,允许在创建时进行更多的逻辑操作。
// Beforeclass Product {Product(int param) {// Constructor logic}}// Afterclass ProductFactory {static Product createProduct(int param) {// Factory logicreturn new Product(param);}}
封装向下转型(Encapsulate Downcast):
问题: 在API中存在向下转型,使得代码依赖于具体的实现类。
解决方法: 将向下转型的操作封装在一个函数中,使得API不再直接依赖于具体的实现。
// Beforevoid process(Object obj) {ConcreteClass concreteObj = (ConcreteClass) obj;// Process using concreteObj}// Aftervoid process(Object obj) {if (obj instanceof ConcreteClass) {processConcrete((ConcreteClass) obj);}}void processConcrete(ConcreteClass concreteObj) {// Process using concreteObj}
以异常取代错误码(Replace Error Code with Exception):
问题: API返回错误码,调用者需要检查错误码并做出相应处理。
解决方法: 使用异常替代错误码,使得调用者可以更自然地处理异常情况。
// Beforeint process() {// Process logicif (errorCondition) {return ERROR_CODE;}return SUCCESS_CODE;}// Aftervoid process() throws CustomException {// Process logicif (errorCondition) {throw new CustomException("Error description");}}
以断言取代错误码(Replace Error Code with Assertion):
问题: 在API中使用错误码来处理不应该发生的情况。
解决方法: 使用断言来标识代码中不应该出现的条件,当条件失败时抛出异常。
// Beforeint process() {// Process logicif (errorCondition) {assert false : "Unexpected error condition";}return SUCCESS_CODE;}// Aftervoid process() {// Process logicassert !errorCondition : "Unexpected error condition";}
引入Null对象(Introduce Null Object):
问题: 在API返回null,调用者需要处理null情况。
解决方法: 引入一个特殊的Null对象,代表缺失的对象,避免返回null。
// BeforeResult getResult() {if (condition) {return new Result();}return null;}// AfterResult getResult() {if (condition) {return new Result();}return new NullResult();}
以对象取代数据值(Replace Data Value with Object):
问题: API传递的参数是一组原始数据。
解决方法: 将这组原始数据封装成一个对象,提高参数的表达力和可读性。
// Beforevoid processData(String name, int age, String address) {// Process logic using name, age, and address}// Afterclass Person {String name;int age;String address;}void processData(Person person) {// Process logic using person object}
通过这些具体的示例代码,我们更清晰地展示了每种重构方法的实际应用场景和代码转换过程。这有助于读者更好地理解如何优化与外部API的交互,提升代码的质量和可维护性。