框架设计,无非就是解决软件的分工生产问题,跟模块化制造汽车一样的原理。我们结合软件的
组件/插件模型
,把它分为三个步骤:
- 设计汽车
模型
,这往往就是最难的环节,就是顶级设计师要做的事情。在软件里面就是软件架构师的任务。 - 生产
部件
,就是分不同车间,按照模型生产发动机、车轮等。在软件中就是初级程序员每天要套架构、实现接口,完成的各个功能模块。 组装
出厂,这一工作由组装车间完成。程序中就是配合配置文件和反射、依赖注入等把各种模块串联起来,并让程序跑起来。
抽象模型
- 基于抽象,定义一个组件接口,即抽象对象。
- 定义一个整体框架,去容纳各个组件对象,就跟车体一样,去承载不同的部件。
// 抽象组件/接口
type Component interface {
Name() string
Run()
}
var (
_frame *frame
once sync.Once
)
type frame struct {
Comps map[string]Component
}
func Frame() *frame {
once.Do(func() {
_frame = &frame{Comps: make(map[string]Component)}
})
return _frame
}
func (p *frame) Register(cmp Component) error {
if _, ok := p.Comps[cmp.Name()]; !ok {
p.Comps[cmp.Name()] = cmp
}
return nil
}
构造部件
- 这一部分就是工人干活的环节,实则不用动太多的脑筋。在MVC的Web框架中,就是你要写的用户控制器、订单控制器、评价控制器以及相关的页面和数据调用的实现。
//发动机
type engine struct{}
func (p *engine) Name() string {
return "engine"
}
func (p *engine) Run() {}
//车轮
type wheel struct{}
func (p *wheel) Name() string {
return "wheel"
}
func (p *wheel) Run() {}
组装运行
- 配置好依赖注入和配置文件,程序自然就跑起来了。这一部分装配工作也往往封装在框架中。
func main() {
frame := component.Frame()
frame = component.Frame()
_ = frame.Register(new(engine))
_ = frame.Register(new(wheel))
for _, cmp := range frame.Comps {
cmp.Run()
}
}
完整代码
package component
import (
"fmt"
"sync"
)
var (
_frame *frame
once sync.Once
)
// 抽象组件/接口
type Component interface {
Name() string
Run()
}
//构造器(单例模式)
type frame struct {
Comps map[string]Component
}
func Frame() *frame {
once.Do(func() {
_frame = &frame{Comps: make(map[string]Component)}
})
return _frame
}
func (p *frame) Register(cmp Component) error {
if _, ok := p.Comps[cmp.Name()]; ok {
return fmt.Errorf("%s already exists.\n", cmp.Name())
}
fmt.Printf("%s already registed.\n", cmp.Name())
p.Comps[cmp.Name()] = cmp
return nil
}
package main
import (
"fmt"
"hello/component"
)
//=========================================
//发动机
type engine struct{}
func (p *engine) Name() string {
return "engine"
}
func (p *engine) Run() {
fmt.Printf("%s start work.\n", p.Name())
}
//车轮
type wheel struct{}
func (p *wheel) Name() string {
return "wheel"
}
func (p *wheel) Run() {
fmt.Printf("%s start work.\n", p.Name())
}
//=========================================
func main() {
//配置文件反射注入
frame := component.Frame()
frame = component.Frame()
_ = frame.Register(new(engine))
_ = frame.Register(new(wheel))
for _, cmp := range frame.Comps {
cmp.Run()
}
}
总结
本篇示例,主要引导如何基于现实场景去做抽象
、抽象
、抽象
编程:
- 所有的框架或设计模式都离不开
抽象+实现
,一定要做到面向抽象编程
。 抽象模型/框架
、实现
、上下文
、客户端
是抽象编程的几个基本组成部分。