使用继承和分层结构组织服务
1 简介
“继承”与“分层结构”结合使用
本文说明 面向对象(OO)方法中的继承 和 信息工程方法中的分层数据模型设计 如何配合使用,可以通过一个简单的 Web 服务示例 来演示。
我们以一个 图书管理系统 为例,结合继承和分层数据模型设计,展示如何实现一个既有灵活性又能有效组织数据的系统。
2 场景描述
数据模型设计中,我们有一个分层结构:
父实体:Item(表示库中的所有物品,包括图书、杂志等)。
子实体:Book 和 Magazine 分别继承通用的 Item 属性,同时有各自的特性。
面向对象方法中:
使用结构体和嵌套组合来实现继承。
基于父结构体的通用操作扩展子类的特殊行为。
在 Web 服务中,我们实现以下功能:
创建和存储不同类型的物品(图书或杂志)。
查询存储的物品,按类型返回。
3 数据模型设计
数据模型采用信息工程方法的分层设计思想:
Item 表示所有物品的基础数据:
通用属性:ID、Name、Category。
Book 和 Magazine 作为具体物品:
Book:额外的属性 Author、ISBN。
Magazine:额外的属性 IssueNumber。
在程序中,数据模型可以通过继承和嵌套的方式实现。
4 Go 实现代码
package main
import (
"encoding/json"
"fmt"
"net/http"
"sync"
)
// Item 表示所有物品的基础结构
type Item struct {
ID int `json:"id"`
Name string `json:"name"`
Category string `json:"category"`
}
// Book 继承了 Item 的基础属性,并扩展了专有属性
type Book struct {
Item
Author string `json:"author"`
ISBN string `json:"isbn"`
}
// Magazine 继承了 Item 的基础属性,并扩展了专有属性
type Magazine struct {
Item
IssueNumber int `json:"issue_number"`
}
// 存储库(模拟数据库)
var (
store = struct {
sync.Mutex
items []Item
}{items: []Item{}}
)
// 添加图书的处理函数
func addBookHandler(w http.ResponseWriter, r *http.Request) {
var book Book
if err := json.NewDecoder(r.Body).Decode(&book); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
book.Category = "Book"
store.Lock()
book.ID = len(store.items) + 1
store.items = append(store.items, book.Item)
store.Unlock()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(book)
}
// 添加杂志的处理函数
func addMagazineHandler(w http.ResponseWriter, r *http.Request) {
var magazine Magazine
if err := json.NewDecoder(r.Body).Decode(&magazine); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
magazine.Category = "Magazine"
store.Lock()
magazine.ID = len(store.items) + 1
store.items = append(store.items, magazine.Item)
store.Unlock()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(magazine)
}
// 查询所有物品的处理函数
func listItemsHandler(w http.ResponseWriter, r *http.Request) {
store.Lock()
defer store.Unlock()
json.NewEncoder(w).Encode(store.items)
}
func main() {
// 路由配置
http.HandleFunc("/books", addBookHandler)
http.HandleFunc("/magazines", addMagazineHandler)
http.HandleFunc("/items", listItemsHandler)
// 启动服务器
fmt.Println("Server is running at http://localhost:8080")
http.ListenAndServe(":8080", nil)
}
5 示例说明
- 数据层的分层结构
数据库层设计可以直接映射到 Item、Book 和 Magazine 结构:
Item:数据库表中表示通用字段(id, name, category)。
Book 和 Magazine:分别对应子表,用于存储特有字段(author, isbn, issue_number)。
在代码中通过嵌套结构体的方式复用了通用字段。
- 继承实现的逻辑
使用 Go 的嵌套结构实现继承关系:
Book 和 Magazine 嵌套了 Item 结构,继承了 Item 的所有通用属性。
每个子类扩展了特有属性(如 Author、IssueNumber)。
- Web 服务的功能
添加物品:通过 /books 和 /magazines 路径分别添加图书和杂志。
查询物品:通过 /items 路径获取所有存储的物品,按 Category 区分。
6 测试
添加一本书请求:
curl -X POST -H "Content-Type: application/json" -d '{
"name": "Go Programming Language",
"author": "Alan A. A. Donovan",
"isbn": "9780134190440"
}' http://localhost:8080/books
响应:
{
"id": 1,
"name": "Go Programming Language",
"category": "Book",
"author": "Alan A. A. Donovan",
"isbn": "9780134190440"
}
添加一本杂志请求:
curl -X POST -H "Content-Type: application/json" -d '{
"name": "National Geographic",
"issue_number": 2023
}' http://localhost:8080/magazines
响应:
{
"id": 2,
"name": "National Geographic",
"category": "Magazine",
"issue_number": 2023
}
查询所有物品请求:
curl http://localhost:8080/items
响应:
[
{
"id": 1,
"name": "Go Programming Language",
"category": "Book"
},
{
"id": 2,
"name": "National Geographic",
"category": "Magazine"
}
]
7 总结
通过 Item 和其子类的设计,将通用属性放在父类,特有属性放在子类,便于扩展和管理,这便是信息工程的分层思想。
通过嵌套结构体实现继承,复用了通用字段并扩展了子类的特性,这便是面向对象的继承思想。
数据模型的分层设计确保了数据库和业务逻辑的一致性。
面向对象方法为扩展和实现逻辑操作(如添加、查询)提供了灵活性。
- 点赞
- 收藏
- 关注作者
评论(0)