工厂模式
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
- 主要解决:主要解决接口选择的问题。
- 何时使用:我们明确地计划不同条件下创建不同实例时。
- 使用场景:
- 日志记录器
- 数据库访问
- 设计一个连接服务器的框架
一个函数可以自行选择用什么类来实现一个或一套方法
package Factoryimport ("fmt""testing")type Restaurant interface {GetFood()}type Donglaishun struct {}func (d *Donglaishun) GetFood() {fmt.Println("东来顺")}type Qingfeng struct {}func (q *Qingfeng) GetFood() {fmt.Println("庆丰")}func NewRestaurant(name string) Restaurant{switch name {case "d":return &Donglaishun{}case "q":return &Qingfeng{}}return nil}func TestNewRestaurant(t *testing.T) {NewRestaurant(d).GetFood()NewRestaurant(d).GetFood()}
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
- 主要解决:主要结局接口选择的问题
- 何时使用:系统的产品有多于一个的产品族,而系统只消费其中的某一族产品
- 使用场景:
- qq换皮肤,一整套一起换
- 生成不同操作系统的程序
一个类通过不同的方法返回不同的类
package Abstract_Factoryimport ("fmt""testing")type Lunch interface{Cook()}type Rise struct {}func (r *Rise) Cook() {fmt.Println("rice")}type Tomato struct {}func (t *Tomato) Cook() {fmt.Println("tomato")}type LunchFactory interface {CreateFood() LunchCreateVegetable() Lunch}type SimpleLunchFactory struct {}func NewSimpleLunchFactory() LunchFactory{return &SimpleLunchFactory{}}func (s *SimpleLunchFactory) CreateFood() Lunch {return &Rise{}}func (s *SimpleLunchFactory) CreateVegetable() Lunch {return &Tomato{}}func TestNewSimpleLunchFactory(t *testing.T) {factory := NewSimpleLunchFactory()food := factory.CreateFood()food.Cook()vegetable := factory.CreateVegetable()vegetable.Cook()}
外观模式
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
- 主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
- 何时使用:
- 客户端不需要知道系统内部的复杂联系,整个系统只需提供一个”接待员”即可。
- 定义系统的入口。
- 使用场景:
- 为复杂的模块或子系统提供外界访问的模块
- 子系统相对独立
- 预防低水平人员带来的风险
通过返回一个简单的接口而实现了复杂的操作
package Facadeimport ("fmt""testing")type CarModel struct {}func NewCarModel() *CarModel {return &CarModel{}}func (c *CarModel) SetModel() {fmt.Fprintf(outputWriter, " CarModel - SetModel\n")}type CarEngine struct {}func NewCarEngine() *CarEngine {return &CarEngine{}}func (c *CarEngine) SetEngine() {fmt.Fprintf(outputWriter, " CarEngine - SetEngine\n")}type CarBody struct {}func NewCarBody() *CarBody {return &CarBody{}}func (c *CarBody) SetBody() {fmt.Fprintf(outputWriter, " CarBody - SetBody\n")}type CarAccessories struct {}func NewCarAccessories() *CarAccessories {return &CarAccessories{}}func (c *CarAccessories) SetAccessories() {fmt.Fprintf(outputWriter, " CarAccessories - SetAccessories\n")}type CarFacade struct {accessories *CarAccessoriesbody *CarBodyengine *CarEnginemodel *CarModel}func NewCarFacade() *CarFacade {return &CarFacade{accessories: NewCarAccessories(),body: NewCarBody(),engine: NewCarEngine(),model: NewCarModel(),}}func (c *CarFacade) CreateCompleteCar() {fmt.Fprintf(outputWriter, "******** Creating a Car **********\n")c.model.SetModel()c.engine.SetEngine()c.body.SetBody()c.accessories.SetAccessories()fmt.Fprintf(outputWriter, "******** Car creation is completed. **********\n")}func TestCarFacade_CreateCompleteCar(t *testing.T) {facade := NewCarFacade()facade.CreateCompleteCar()}
建造者模式
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
- 主要解决:主要解决在软件系统中,有时候面临着”一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
- 何时使用:一些基本部件不会变,而其组合经常变化的时候
- 场景:
- 套餐,东西不变,但组合一直变
一些基本部件不会变,而组合经常变化
- 套餐,东西不变,但组合一直变
package Builderimport ("fmt""testing")type Builder interface {Build()}type Director struct {builder Builder}func NewDirector(b Builder) Director {return Director{builder: b}}func (d *Director) Construct() {d.builder.Build()}type ConcreteBuilder struct {built bool}func NewConcreteBuilder() ConcreteBuilder {return ConcreteBuilder{false}}func (b *ConcreteBuilder) Build() {b.built = true}type Product struct {Built bool}func (b *ConcreteBuilder) GetResult() Product {return Product{b.built}}func TestConcreteBuilder_GetResult(t *testing.T) {builder := NewConcreteBuilder()director := NewDirector(&builder)director.Construct()product := builder.GetResult()fmt.Println(product.Built)}
桥接模式
将抽象部分与实现部分分离,使它们都可以独立的变化。
- 主要解决:在有很多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不方便
- 何时使用:实现系统可能有多个角度分类,每一种角度都可能变化
- 场景:
- 系统需要在构建的抽象化角色于具体化角色之间增加更多灵活性(模型-实例)
- 不希望使用继承或因为多层次导致系统类的个数急剧增加的系统
- 一个类存在两个独立变化的维度,且两个维度都需要扩展
具体的描述某些维度
package Bridageimport ("fmt""time""testing")type Draw interface {DrawCircle(radius, x, y int)}type RedCircle struct {}func (g *RedCircle) DrawCircle(radius, x, y int) {fmt.Println("radius、x、y:", radius, x, y)}type YellowCircle struct {}func (g *YellowCircle) DrawCircle(radius, x, y int) {fmt.Println("radius、x、y:", radius, x, y)}type Shape struct {draw Draw}func (s *Shape) Shape(d Draw) {s.draw = dtime.Now().Unix()}type Circle struct {shape Shapex inty intradius int}func (c *Circle) Constructor(x int, y int, radius int, draw Draw) {c.x = xc.y = yc.radius = radiusc.shape.Shape(draw)}func (c *Circle) Cook() {c.shape.draw.DrawCircle(c.radius, c.x, c.y)}func TestCircle_Draw(t *testing.T) {redCircle := Circle{}redCircle.Constructor(100, 100, 10, &RedCircle{})yellowCircle := Circle{}yellowCircle.Constructor(200, 200, 20, &YellowCircle{})redCircle.Cook()yellowCircle.Cook()}
命令模式
将一个请求封装成一个对象,从而可以用不同的请求对客户进行参数化。
- 主要解决:某些场合下,紧耦合的设计无法满足行为
- 何时使用:在某些场合,比如要对行为进行”记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将”行为请求者”与”行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
- 使用场景:
- GUI的每一个按钮
- 模拟CMD
使用一个函数可以灵活的使用其方法
package Commandimport ("fmt""testing")type Person struct {name stringcmd Command}type Command struct {person *Personmethod func()}func NewCommand(p *Person, method func()) Command {return Command{person: p,method: method,}}func (c *Command) Execute() {c.method()}func NewPerson(name string, cmd Command) Person {return Person{name: name,cmd: cmd,}}func (p *Person) Buy() {fmt.Println(fmt.Sprintf("%s is buying ", p.name))p.cmd.Execute()}func (p *Person) Cook() {fmt.Println(fmt.Sprintf("%s is cooking ", p.name))p.cmd.Execute()}func (p *Person) Wash() {fmt.Println(fmt.Sprintf("%s is washing ", p.name))p.cmd.Execute()}func (p *Person) Listen() {fmt.Println(fmt.Sprintf("%s is Listening ", p.name))}func (p *Person) Talk() {fmt.Println(fmt.Sprintf("%s is Talking ", p.name))p.cmd.Execute()}func TestCommand_Execute(t *testing.T) {laowang := NewPerson("wang", NewCommand(nil, nil))laozhang := NewPerson("zhang", NewCommand(&laowang, laowang.Listen))laofeng := NewPerson("feng", NewCommand(&laozhang, laozhang.Buy))laoding := NewPerson("ding", NewCommand(&laofeng, loafeng.Cook))laoli := NewPerson("li", NewCommand(&laoding, laoding.Wash))laoli.Talk()}
