Java封装艺术:从访问控制到设计模式实战

37 阅读2分钟

面向对象的封装本质

封装是面向对象三大特性(封装、继承、多态)的基石,它通过隐藏实现细节和暴露有限接口,降低系统耦合度。想象灯泡的开关设计:

// 低耦合设计:只暴露必要接口
Light light = new Light();
light.turnOn(); // 用户无需了解内部电路

// 高耦合设计:暴露实现细节
Light light2 = new Light();
light2.打开电路1(); // 用户需了解内部实现
light2.打开电路2();
light2.打开电路3();

封装的必要性

当业务需求变化时,未封装的代码将面临灾难性修改。以用户年龄校验为例:

// 未封装:100处赋值点需要修改
public class Person {
    public int age; // 直接暴露属性
}

// 封装后:只需修改setAge方法
public class Person {
    private int age;
    
    public void setAge(int age) {
        this.age = Math.max(0, Math.min(age, 100));
    }
}

访问控制四重门

Java提供精确的访问控制机制:

修饰符同类同包子类其他包
private✔️
(默认)✔️✔️
protected✔️✔️✔️
public✔️✔️✔️✔️

protected的跨包访问

// 子类可访问父类protected成员
public class PersonSubClass extends Person {
    public PersonSubClass() {
        this.id = 1; // 允许访问protected字段
    }
}

JavaBean规范与序列化

遵循JavaBean规范是实现框架集成的关键:

public class Cat {
    private String name;
    private boolean cute;
    
    // 非布尔属性getter
    public String getName() { return name; }
    
    // 布尔属性getter
    public boolean isCute() { return cute; }
    
    // 序列化演示
    public static void main(String[] args) {
        Cat cat = new Cat("喵", true);
        String json = JSON.toJSONString(cat); // 依赖getter
        
        Cat parsedCat = JSON.parseObject(json, Cat.class); // 依赖setter
    }
}

核心规范

  • 非布尔属性:getXxx()
  • 布尔属性:isXxx()
  • 设置方法:setXxx()

静态工厂方法实践

Effective Java推荐的创建模式,相比构造器优势明显:

public class Cat {
    private static final Cat INVALID_CAT = new Cat("Invalid", true);
    
    private Cat(String name, boolean cute) { // 构造器私有化
        // ...
    }
    
    // 1. 方法名自描述
    public static Cat newCuteCat(String name) {
        if (name == null) return INVALID_CAT;
        
        // 3. 返回子类对象
        if (name.contains("white")) return new WhiteCat(name);
        
        // 4. 复用已有对象
        return name.equals("default") ? DEFAULT_CAT : new Cat(name, true);
    }
    
    // 2. 不强制创建新对象
    public static Cat getInstance() {
        return CACHE.get();
    }
}

五大优势

  1. 方法名明确创建意图(newCuteCat vs new Cat(true)
  2. 避免不必要的对象创建
  3. 可返回任意子类型
  4. 实现对象缓存复用
  5. 服务提供者框架的基础

Builder模式解决参数膨胀

当构造参数过多时,Builder模式提供优雅解决方案:

Person person = Person.builder()
    .withFirstName("张")
    .withLastName("三")
    .withAge(30)
    .withAddress("北京市")
    .withPhone("13800138000")
    .build();

实现要点

  1. 创建静态内部Builder类
  2. 链式设置方法(返回Builder自身)
  3. build()方法返回最终对象

突破包级访问限制

在特殊场景下,可通过同名包突破访问限制:

// 在com.github.hcsp包中创建类
package com.github.hcsp; 

public class PackageAccessor {
    void access() {
        InternalClass obj = new InternalClass(); // 访问包级私有类
    }
}

包访问机制

Java模块化系统

JDK9引入的模块系统提供更强封装:

module com.example.myapp {
    exports com.example.api; // 导出公共API包
    hides com.example.internal; // 隐藏实现包
}

模块系统