面试题答案
一键面试架构设计思路
- 分层架构:
- 表现层(Presentation Layer):负责与用户交互,接收用户请求并返回响应。通常使用接口定义对外暴露的服务,如 RESTful API 接口。这样可以方便不同客户端(Web、移动端等)调用,且易于替换实现,例如从基于 Servlet 的实现切换到 Spring WebFlux。
- 业务逻辑层(Business Logic Layer):处理具体的业务逻辑。通过抽象类或接口将业务逻辑进行抽象,不同的业务模块实现这些抽象。例如,对于一个电商系统的订单模块,可定义
OrderService
接口,具体的订单创建、查询、修改等业务逻辑由实现类完成。使用抽象类可以提供一些通用的业务逻辑实现,子类继承并按需扩展。 - 数据访问层(Data Access Layer):负责与数据库或其他数据源交互。通过接口定义数据访问方法,如
UserDao
接口定义对用户数据的增删改查操作,具体的实现类可以根据使用的数据库(如 MySQL、Oracle)不同而不同,实现数据访问层与业务逻辑层的解耦。
- 解耦模块依赖:
- 使用接口来定义模块之间的交互。例如,业务逻辑层的某个模块依赖另一个模块的服务,通过依赖接口而不是具体实现类,降低模块间的耦合度。假设模块 A 需要调用模块 B 的功能,模块 A 只依赖模块 B 定义的接口,这样模块 B 的内部实现变化不会影响到模块 A。
- 抽象类可以用于抽取一些通用的功能和状态,减少重复代码。例如,多个业务模块可能都需要进行日志记录、权限验证等通用操作,可以将这些操作封装在抽象类中,子类继承抽象类并复用这些功能。
- 提高可扩展性和可维护性:
- 可扩展性:通过接口和抽象类,新的功能模块可以很容易地添加进来。例如,当系统需要支持新的支付方式时,只需要实现支付相关的接口,然后在业务逻辑层进行相应的调用即可,而不需要修改大量已有的代码。
- 可维护性:清晰的分层和接口抽象使得代码结构更清晰,每个模块的职责明确。当某个模块出现问题时,开发人员可以快速定位到问题所在模块,而不会影响到其他模块。同时,修改某个模块的实现只需要关注该模块内部,只要接口不变,对其他模块无影响。
代码示例
- 数据访问层:
- 定义
UserDao
接口:
- 定义
public interface UserDao {
User findUserById(int id);
void saveUser(User user);
}
- 具体实现类 `MysqlUserDao`:
public class MysqlUserDao implements UserDao {
@Override
public User findUserById(int id) {
// 从 MySQL 数据库查询用户
return null;
}
@Override
public void saveUser(User user) {
// 将用户保存到 MySQL 数据库
}
}
- 业务逻辑层:
- 定义
UserService
接口:
- 定义
public interface UserService {
User getUserById(int id);
void registerUser(User user);
}
- 抽象类 `AbstractUserService` 提供一些通用逻辑:
public abstract class AbstractUserService implements UserService {
protected UserDao userDao;
public AbstractUserService(UserDao userDao) {
this.userDao = userDao;
}
@Override
public User getUserById(int id) {
return userDao.findUserById(id);
}
}
- 具体业务实现类 `DefaultUserService`:
public class DefaultUserService extends AbstractUserService {
public DefaultUserService(UserDao userDao) {
super(userDao);
}
@Override
public void registerUser(User user) {
// 业务逻辑,如验证用户信息,调用 userDao 保存用户
userDao.saveUser(user);
}
}
- 表现层(简化示例,假设使用 Spring Boot):
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/user/{id}")
public User getUserById(@PathVariable int id) {
return userService.getUserById(id);
}
}
在上述示例中,通过接口和抽象类实现了分层架构,解耦了模块间的依赖,提高了系统的可扩展性和可维护性。数据访问层的实现可以根据需要替换,业务逻辑层通过抽象类复用通用逻辑,表现层通过依赖接口调用业务逻辑,整个系统结构清晰,易于维护和扩展。