工厂模式
工厂模式,工厂模式一般用于初始化对象,将对象实例化的过程抽象,可以适配组装出不同的对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| type User struct { ID int64 Name string
Address string Orgnize string }
type Options func(user *User)
func NewUser(id int64, name string, opts ...Options) *User { user := &User{ ID: id, Name: name, }
for _, o := range opts { o(user) } return user }
func WithAddress(user *User) { user.Address = "Wuhan" }
func WithOrgnize(user *User) { user.Orgnize = "Developer" }
func main() { u := NewUser(1, "mitaka", WithOrgnize, WithAddress) fmt.Println(u) }
|
责任链模式
责任链模式通常会用到中间件中,例如Gin
框架中使用recover
和log
中间件,使用的就是责任链模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type Handler func(writer http.ResponseWriter, request *http.Request)
func Hello(writer http.ResponseWriter, request *http.Request) { writer.Write([]byte("hello")) }
func Filter(next Handler) Handler { return func(writer http.ResponseWriter, request *http.Request) { log.Println("get a http requese from: ", request.RemoteAddr) start := time.Now() next(writer, request) log.Println("this request spend ", time.Now().Sub(start).String()) } }
func main() { http.HandleFunc("/", Filter(Hello)) }
|
封装和抽象
在实现一个框架的过程中,会经常使用到封装的能力,将相同的参数和请求疯转到一起,将功能封装到接口中。
例如将http请求中的请求和响应封装成一个结构体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import "net/http"
type Context struct { w http.ResponseWriter r *http.Request }
func NewContext(w http.ResponseWriter, r *http.Request) *Context { return &Context{w: w, r: r} }
func (c *Context) ReplyOK() { c.w.WriteHeader(http.StatusOK) }
func (c *Context) ReplyNotFound() { c.w.WriteHeader(http.StatusNotFound) }
|
处理请求时,通过该请求即可。
将http请求封装成一个interface
,通过内部接口实现http
服务启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| package main
import ( "net/http" )
type Handler func(ctx *Context)
type HttpServerHandler interface { Route(pattern string, handler Handler) Start(addr string) error Use(filters ...FilterFunc) http.Handler }
type HttpServer struct { name string Filters []FilterFunc handlers map[string]Handler }
var _ HttpServerHandler = &HttpServer{}
func NewHttpServer(name string) HttpServerHandler { return &HttpServer{ name: name, Filters: make([]FilterFunc, 0, 2), handlers: make(map[string]Handler), } }
func (h *HttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { c := NewContext(w, r) handler, ok := h.handlers[c.r.URL.Path] if !ok { c.ReplyNotFound() } handler(c) }
func (h *HttpServer) Route(pattern string, handler Handler) { for _, filter := range h.Filters { handler = filter(handler) } h.handlers[pattern] = handler http.Handle(pattern, h) }
func (h *HttpServer) Start(addr string) error { return http.ListenAndServe(addr, nil) }
func (h *HttpServer) Use(filters ...FilterFunc) { h.Filters = append(h.Filters, filters...) }
|
其中,使用Use方法添加中间件。中间件则使用了责任链的设计模式或者装饰器设计模式
1 2 3 4 5 6 7 8 9 10
| type FilterFunc func(next Handler) Handler
func LogFilter(next Handler) Handler { return func(ctx *Context) { log.Println("get a http requese from: ", ctx.r.RemoteAddr) start := time.Now() next(ctx) log.Println("this request spend ", time.Now().Sub(start).String()) } }
|