类的设计
- 单一职责原则:每个类应该只负责一项主要功能。例如,在一个电商系统中,将用户信息管理功能封装在
UserService
类中,订单管理功能封装在OrderService
类中。这样当需求变化时,只需要修改对应的类,不会影响其他功能模块。
public class UserService {
// 用户信息相关操作方法
public void registerUser(User user) {
// 注册逻辑
}
public User getUserById(int userId) {
// 获取用户逻辑
return null;
}
}
- 高内聚低耦合:类内部的方法和数据应该紧密相关,并且与其他类之间的依赖关系要尽量少。例如,在
UserService
类中,所有方法都围绕用户信息操作,不包含与订单等其他业务无关的逻辑。同时,UserService
在获取数据库连接时,可以通过依赖注入(如使用Spring框架),而不是在类内部直接创建数据库连接对象,减少与数据库连接类的耦合。
访问修饰符的使用
- private:用于修饰类的成员变量和方法,使其只能在类内部访问。这是实现数据隐藏的关键。例如,在
User
类中,用户的密码字段应该设为private
,防止外部直接访问和修改。
public class User {
private String password;
// 提供修改密码的方法,而不是直接暴露密码字段
public void setPassword(String newPassword) {
// 密码复杂度验证等逻辑
this.password = newPassword;
}
}
- protected:修饰的成员变量和方法可以被同一包内的类以及子类访问。比如,在一个基础的
BaseEntity
类中有一些通用的属性和方法设为protected
,其子类(如User
、Product
等实体类)可以继承并使用这些属性和方法,同时又限制了包外无关类的访问。
public class BaseEntity {
protected int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public class User extends BaseEntity {
// User类可以使用BaseEntity中的id属性和相关方法
}
- default(包访问权限):没有修饰符时,成员变量和方法具有包访问权限,即同一包内的类可以访问。在一个模块的包内,如果有些工具类的方法不需要暴露给其他模块,可以使用包访问权限。例如,在
com.example.util
包下有一个StringUtils
类,其中的一些字符串处理方法只供本包内的类使用。
package com.example.util;
class StringUtils {
static String formatString(String str) {
// 字符串格式化逻辑
return str;
}
}
- public:修饰的成员变量和方法可以被任何类访问。通常用于对外提供的接口方法,如
UserService
类中的registerUser
和getUserById
方法,供其他模块调用。
数据隐藏
- 使用访问器方法(getter和setter):通过提供访问器方法来间接访问和修改类的私有成员变量。这样可以在访问器方法中添加逻辑控制,如数据验证。例如,在
User
类中设置age
字段时,可以在setAge
方法中验证年龄是否合法。
public class User {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0 && age <= 120) {
this.age = age;
} else {
throw new IllegalArgumentException("Invalid age value");
}
}
}
- 不可变对象:对于一些数据不希望被修改的情况,可以设计成不可变对象。例如,
java.lang.String
类就是不可变的。在自定义类中,如表示日期范围的DateRange
类,可以将其设计为不可变。
import java.util.Date;
public final class DateRange {
private final Date startDate;
private final Date endDate;
public DateRange(Date startDate, Date endDate) {
this.startDate = new Date(startDate.getTime());
this.endDate = new Date(endDate.getTime());
}
public Date getStartDate() {
return new Date(startDate.getTime());
}
public Date getEndDate() {
return new Date(endDate.getTime());
}
}
优化建议
- 文档化:对类和方法添加详细的JavaDoc注释,说明类的功能、方法的参数和返回值等,提高代码的可读性和可维护性。
- 避免过度封装:虽然封装很重要,但也要注意不要过度封装导致代码复杂度过高,难以理解和调试。要在安全性和开发效率之间找到平衡。
- 持续重构:随着项目的发展,需求会发生变化,要定期对代码进行重构,检查封装是否仍然合理,是否需要调整访问修饰符或类的设计。