Hey小伙伴们,今天要给大家安利一篇优秀的文章,相信大家通过仔细阅读,一定会有所收货!
🔗【文章链接】:程序员启示录
💖 推荐理由:这篇文章是由 江拥羡橙 撰写的,笔者深刻地记录了多年工作的心得与领悟,借由本文,愿为同仁们献上点滴启示。特别欣赏笔者结尾之言:大丈夫行于乱世,当光明磊落。即使处于逆境,也当屈身守分,以待天时,不可与命抗争也。
我们也要学习刘皇叔的这句话啊,在等待时机的同时,不断积累自己的力量,完善自我,以便在机会来临时能够抓住。
软件开发过程中,架构设计是至关重要的环节,尤其对于小型项目来说,合理的架构不仅能帮助团队避免后期的重构麻烦,还能大大提升代码的可维护性和可扩展性。尽管小型项目看似不需要复杂的架构设计,但实际应用中,如果架构设计得当,能有效提高开发效率,并为未来可能的扩展打下坚实的基础。在这篇文章中,我们将探讨一些简单易懂的架构设计原则,并结合小型项目的特点,说明如何将这些原则有效应用到实际开发中。
下面我会结合实际的 Java 代码来演示如何在小型项目中实现高效的模块化设计,并应用一些常见的架构设计原则,如单一职责原则、接口与实现分离、依赖倒转原则等。
假设我们正在开发一个简单的待办事项应用,功能包括:
我们将使用 Java 编写代码,并应用前面提到的架构设计原则。
首先,我们将待办事项功能拆分成不同的类,每个类负责一个单一的职责。
package com.example.todo.model;
// TodoItem.java - 代表待办事项实体
public class TodoItem {
private String title;
private boolean isCompleted;
public TodoItem(String title) {
this.title = title;
this.isCompleted = false;
}
public String getTitle() {
return title;
}
public boolean isCompleted() {
return isCompleted;
}
public void markAsCompleted() {
this.isCompleted = true;
}
}
package com.example.todo.service;// TodoService.java - 业务逻辑层
import com.example.todo.model.TodoItem;
import com.example.todo.repository.TodoRepository;
import java.util.List;
public class TodoService {
private TodoRepository todoRepository;
public TodoService(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
public void addTodoItem(String title) {
TodoItem item = new TodoItem(title);
todoRepository.save(item);
}
public List<TodoItem> getAllTodoItems() {
return todoRepository.findAll();
}
public void markItemAsCompleted(int index) {
TodoItem item = todoRepository.findByIndex(index);
if (item != null) {
item.markAsCompleted();
todoRepository.save(item); // 保存更新后的状态
}
}
}
在代码中,我们通过接口将数据访问层抽象出来,并提供不同的实现,这样可以保持模块的解耦。
package com.example.todo.repository;
// TodoRepository.java - 数据访问接口
import com.example.todo.model.TodoItem;
import java.util.List;
public interface TodoRepository {
void save(TodoItem item);
List<TodoItem> findAll();
TodoItem findByIndex(int index);
}
package com.example.todo.repository;
// InMemoryTodoRepository.java - 内存存储的实现
import com.example.todo.model.TodoItem;
import java.util.ArrayList;
import java.util.List;
public class InMemoryTodoRepository implements TodoRepository {
private List<TodoItem> todoItems = new ArrayList<>();
@Override
public void save(TodoItem item) {
todoItems.add(item);
}
@Override
public List<TodoItem> findAll() {
return todoItems;
}
@Override
public TodoItem findByIndex(int index) {
if (index >= 0 && index < todoItems.size()) {
return todoItems.get(index);
}
return null;
}
}
通过接口依赖而不是具体实现,使得高层模块 (TodoService
) 不依赖低层模块 (InMemoryTodoRepository
) 的具体实现,而是依赖于抽象接口 (TodoRepository
)。
在上面的代码中,TodoService
类依赖 TodoRepository
接口,而不是 InMemoryTodoRepository
类的具体实现。这样,我们可以很方便地将数据存储方式从内存切换到数据库、文件等,而不需要修改 TodoService
的代码。
在实际开发中,我们通常将系统分为不同的层次,如控制层、服务层、数据访问层。
package com.example.todo.controller;
// TodoController.java - 控制器层
import com.example.todo.repository.InMemoryTodoRepository;
import com.example.todo.service.TodoService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TodoController {
private final TodoService todoService;
public TodoController() {
this.todoService = new TodoService(new InMemoryTodoRepository()); // 使用内存存储
}
@GetMapping("/")
public String index(Model model) {
model.addAttribute("todos", todoService.getAllTodoItems());
return "index"; // 视图名称应该是 "index" 而不是 "index.html"
}
@PostMapping("/add")
public String addTodo(@RequestParam("title") String title) {
todoService.addTodoItem(title);
return "redirect:/"; // 添加后重定向到首页
}
@PostMapping("/complete")
public String completeTodo(@RequestParam("index") int index) {
todoService.markItemAsCompleted(index);
return "redirect:/"; // 完成后重定向到首页
}
}
假设将来我们要添加更多的功能,比如按照优先级排序待办事项,或者支持用户登录。由于我们采用了接口与实现分离的设计,扩展功能时我们不需要修改已有的代码,只需要增加新的模块或类。
例如,假如我们要添加一个 待办事项优先级功能,我们可以这样做:
// PriorityTodoItem.java - 扩展 TodoItem 类,加入优先级功能
public class PriorityTodoItem extends TodoItem {
private int priority;
public PriorityTodoItem(String title, int priority) {
super(title);
this.priority = priority;
}
public int getPriority() {
return priority;
}
}
在 TodoService
中,我们可以使用新的 PriorityTodoItem
类来代替 TodoItem
类,从而实现待办事项的优先级功能,而不影响已有的 TodoItem
使用者。
接下来我将结合 Thymeleaf 和 Spring Boot 来实现一个完整的待办事项应用。我们将使用之前提到的架构设计原则,并通过 Thymeleaf
来实现前端展示。
├── src/main/java/com/example/todo/
│ ├── controller/ # 控制器层
│ │ └── TodoController.java
│ ├── model/ # 模型层
│ │ └── TodoItem.java
│ ├── repository/ # 数据访问层
│ │ └── TodoRepository.java
│ │ └── InMemoryTodoRepository.java
│ ├── service/ # 服务层
│ │ └── TodoService.java
│ └── TodoAppApplication.java # Spring Boot 启动类
│
├── src/main/resources/
│ ├── templates/ # Thymeleaf 模板文件
│ │ └── index.html
│ ├── application.properties
│
└── pom.xml # Maven 配置文件
在 pom.xml
中添加 Spring Boot
和 Thymeleaf
的依赖:
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Thymeleaf Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Boot DevTools for hot reload (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
在 src/main/resources/application.properties
中,设置端口和模板路径等配置:
# 设置应用运行端口
server.port=8080
# Thymeleaf 配置(默认配置可以省略)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>待办事项</title>
<!-- 引入 Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- 可选:引入 Google 字体 -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<!-- 可选:引入 FontAwesome 图标库 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
<style>
/* 自定义样式 */
body {
font-family: 'Roboto', sans-serif;
}
</style>
</head>
<body class="container mt-5">
<h1 class="text-center">待办事项</h1>
<!-- 添加待办事项表单 -->
<form action="/add" method="post" class="mb-4">
<div class="mb-3">
<label for="title" class="form-label">添加待办事项:</label>
<input type="text" id="title" name="title" class="form-control" required>
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
<h2>待办事项列表</h2>
<ul class="list-group">
<th:block th:each="todo, iterStat : ${todos}">
<li class="list-group-item d-flex justify-content-between align-items-center">
<span th:text="${todo.title}"></span>
<span th:if="${todo.isCompleted}" class="badge bg-success">[完成]</span>
<!-- 完成操作按钮 -->
<form action="/complete" method="post" th:object="${todo}" class="d-inline">
<input type="hidden" th:value="${iterStat.index}" name="index">
<button type="submit" class="btn btn-success btn-sm" th:if="${not todo.isCompleted}">
<i class="fas fa-check"></i> 标记为完成
</button>
</form>
</li>
</th:block>
</ul>
<!-- 引入 Bootstrap JS 和 Popper.js -->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.min.js"></script>
</body>
</html>
link
标签)。它为表单、按钮、列表等提供了响应式设计和现代化样式。Roboto
字体,使页面字体更美观。<style>
标签中增加了简单的自定义样式,以便覆盖默认样式或进行微调。form-control
, btn
, btn-primary
, list-group
等来美化表单、按钮和列表。总之,架构设计在小型项目中的作用远超我们的预期。通过遵循一些基本的设计原则,比如模块化、分层结构、松耦合和高内聚等,可以为项目的长期发展提供极大的支持。良好的架构设计不仅能够帮助我们快速应对项目需求的变化,还能让代码在未来的维护与扩展中变得更加轻松。希望本文的架构设计原则能够帮助你在小型项目的开发中,打造一个高效、可维护、易扩展的系统架构,为项目的成功奠定基础。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。