golang设计模式介绍(内含各个模式的java对比)代码解读

golang设计模式介绍

设计模式是面向对象软件的经验,是通常设计问题的解决方案,每一种设计模式系统的命名,解释和评价了面向对象中一个重要的和重复出现的设计。
在这里插入图片描述以下一一介绍这些设计模式

1.1工厂设计模式

就是创建一个工厂类负责实例化对象,就像汽车制造厂来生产汽车一样工厂负责创建产品,客户端访问工厂实例化对象,uml图:
请添加图片描述

package main

import "fmt"

type Fruit interface {
	grant()
	pick()
}
type Apple struct {
	name string
}
type Orange struct {
	name string
}

func (Apple) grant() {
	fmt.Print("种植苹果")
}
func (Apple) pick() {
	fmt.Print("摘苹果")

}
func (*Orange) pick() {
	fmt.Print("zai橘子")

}
func (*Orange) grant() {
	fmt.Print("种植橘子")

}
func NewFruit(i int) Fruit {
	switch i {
	case 1:
		return Apple{}

	case 2:
		return &Orange{}

	}
	return nil
}
func main() {
	fruit1 := NewFruit(1)
	fruit2 := NewFruit(2)
	fruit1.grant()
	fruit1.pick()
	fruit2.grant()
	fruit2.pick()

}
/*在这个代码片段中,指针用于将方法附加到结构体的指针上而不是结构体本身。在 func (*orange) 中使用了一个指向 orange 结构体的指针,而在 func (apple) 中没有使用指针。

当我们使用非指针接收器时,任何更改都是使用值副本进行的,并且对调用者没有影响。而如果我们使用指针接收器,则可以修改原始对象。

在这段代码中, newfruit() 函数通过 switch 语句返回两种不同类型(apple 和 orange)。当我们返回 apple{} 时,我们正在返回对象本身,而 &orange{} 则返回指向对象的指针。
指针的存储结构和存储位置取决于指针所在的环境和计算机的体系结构。下面是一些常见的情况:

在c语言中,指针通常使用一个整数来表示内存地址。这个整数的大小和具体值取决于编译器和操作系统。
在大多数计算机体系结构中,指针占用一定的内存空间,以便存储指向的地址。在32位架构上通常使用4个字节存储指针,在64位架构上通常使用8个字节存储指针。
在许多高级语言中,指针的实现方式可能会不同。例如,在java中,指针被称为“引用”,并且它们不直接暴露给程序员,而是由虚拟机管理和处理。
指针的存储位置通常在程序的堆栈或堆中。在函数调用期间,指针通常被压入函数的堆栈中,并在函数返回时弹出。在动态分配内存等操作期间,指针通常保存在堆中,直到该内存被释放。然而,具体存储位置也可能取决于指针的使用场景和编程语言。*/

golang单例设计模式

通过单例设计模式可以保证该系统中,应用该模式的类只有一个实例,即一个类只有一个实例对象,例如:系统里边的垃圾回收机制,数据库的连接池等等都是单例设计模式请添加图片描述

package main

import (
	"fmt"
	"sync"
)


type Singleton interface {
	dosomething()
}

// 首字母小写 私有的 不能导出
type singleton struct {
}

func (s *singleton) dosomething() {
	fmt.Println("do some thing")
}

var (
	once     sync.Once
	instance *singleton
)

func GetInstance() Singleton {
	once.Do(
		func() {
			instance = &singleton{}
		},
	)
	return instance
}

func main() {
	s1 := GetInstance()
	fmt.Printf("s1: %p\n", s1)
	s2 := GetInstance()
	fmt.Printf("s2: %p\n", s2)
}
/*sync.once 是 go 语言标准库 sync 包中的一个类型,它提供了一种安全且高效的方式来执行某个函数只有一次。

在给定的函数(如上述代码中的匿名函数)首次被调用时,do 方法会将该函数作为参数传入,然后执行该函数。此后,无论 do 方法被调用多少次,它都不会再次执行这个函数。

换句话来说,sync.once 确保给定的函数在程序运行期间仅能被执行一次,即使多个 goroutine 并发调用 do() 方法也没关系,因为该函数只会被执行一次。通常情况下,使用 sync.once 来实现单例模式非常方便。*/

类比于java的单例设计模式:

1.饿汉式

饿汉式是指该单例实例在类加载的时候就创建出来了,线程安全但无法实现懒加载

public class Singleton{
    //私有构造方法
    private Singleton(){}

    //使用静态变量来存储唯一实例
    private static Singleton singleton = new Singleton();

    //公共静态方法返回该实例
    public static Singleton getSingleton(){
        return singleton;
    }
}

懒汉式

懒汉式是指在首次调用getSingleton()方法时创建单例,可以实现延迟加载但线程不安全。

public class Singleton {
    //私有化构造器
    private Singleton() {}

    private static Singleton singleton = null;

    // 公有静态方法获取唯一实例
    public static synchronized Singleton getSingleton() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

双重校验锁

双重检查锁定是对懒汉式单例模式的改进,通过增加同步块来解决线程并发问题,在性能和线程安全间更好的平衡。

public class Singleton{
    // 私有构造器
    private Singleton(){}

    private static volatile Singleton singleton = null;

    // 公有静态方法获取唯一实例
    public static Singleton getSingleton(){
        if(singleton == null){
            synchronized(Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

1.3 抽象工厂设计模式

抽象工厂设计模式 是围绕一个超级工厂,创建其他的工厂,这种设计类型的模式属于是创建型模式
抽象工厂解决的问题是:
在工厂模式中,一个工厂对应一种具体的产品,但是我们有时候可能需要工厂提供多个产品对象,而不是单一产品对象

俩个概念

产品等级结构 铲平的等级结构就是产品的继承结构 ,如一个模型工厂,可以画处圆形 ,长方形和正方形的模型,这里的抽象模型工厂和具体的模型构成了产品等级结构
== 产品族== 在抽象工厂模式中,产品组指的是同一个工厂生产的位于不同产品等级结构的一组产品,如模具工厂生产的红色圆形模具,圆形模具属于魔性产品等级中,红色属于颜料产品等级结构中。

package main

import "fmt"

//Shape 形状接口
type Shape interface {
	Draw()
}

//Color 色彩接口
type Color interface {
	Fill()
}

//Circle 实现模型接口的圆形类
type Circle struct{}

//Square 实现模型接口的正方形类
type Square struct{}

//Draw Circle类的Draw方法
func (c Circle) Draw() {
	fmt.Println("画圆")
}

//Draw Square类的Draw方法
func (s Square) Draw() {
	fmt.Println("画正方形")
}

//Red 实现色彩接口的红色类
type Red struct{}

//Green 实现色彩接口的绿色类
type Green struct{}

//Fill 红色类的Fill方法
func (r Red) Fill() {
	fmt.Println("填充红色")
}

//Fill 绿色类的Fill方法
func (g Green) Fill() {
	fmt.Println("填充绿色")
}

//AbstractFactory 抽象工厂接口
type AbstractFactory interface {
	GetShape(shapeName string) Shape
	GetColor(colorName string) Color
}

//ShapeFactory 模型工厂的类
type ShapeFactory struct{}

//ColorFactory 色彩工厂的类
type ColorFactory struct{}

//GetShape 模型工厂实例获取模型子类的方法
func (sh ShapeFactory) GetShape(shapeName string) Shape {
	switch shapeName {
	case "circle":
		return &Circle{}
	case "square":
		return &Square{}
	default:
		return nil
	}
}

//GetColor 模型工厂实例不需要色彩方法
func (sh ShapeFactory) GetColor(colorName string) Color {
	return nil
}

//GetShape 色彩工厂实例不需要获取模型方法
func (cf ColorFactory) GetShape(shapeName string) Shape {
	return nil
}

//GetColor 色彩工厂实例,获取具体色彩子类
func (cf ColorFactory) GetColor(colorName string) Color {
	switch colorName {
	case "red":
		return &Red{}
	case "green":
		return &Green{}
	default:
		return nil
	}
}

//FactoryProducer 超级工厂类,用于获取工厂实例
type FactoryProducer struct{}

//GetFactory 获取工厂方法
func (fp FactoryProducer) GetFactory(factoryname string) AbstractFactory {
	switch factoryname {
	case "color":
		return &ColorFactory{}
	case "shape":
		return &ShapeFactory{}
	default:
		return nil
	}
}

//NewFactoryProducer 创建FactoryProducer类
func NewFactoryProducer() *FactoryProducer {
	return &FactoryProducer{}
}

func main() {

	superFactory := NewFactoryProducer()
	colorFactory := superFactory.GetFactory("color")
	shapeFactory := superFactory.GetFactory("shape")

	red := colorFactory.GetColor("red")
	green := colorFactory.GetColor("green")

	circle := shapeFactory.GetShape("circle")
	square := shapeFactory.GetShape("square")

	// 红色的圆形
	circle.Draw()
	red.Fill()

	// 绿色的方形
	square.Draw()
	green.Fill()

}

Golang建造者模式

建造者模式使用多个简单的对象一步步构建成一个复杂的对象
什么是建造者模式:
一个builder 类 会一步步的构造最终对象,该builder类是独立于其他对象的
解决的问题是
在软件系统中,有的时候面临一个复杂的对象的创建工作,通常这个复杂对象各个部分的子对象用一定的算法构造成,由于需求的变化 ,这个复杂对象的哥哥部分通常会发生巨大的变化,所以,将各个对象独立出来,容易修改请添加图片描述

package main

import "fmt"

type Builder interface {
	buildDisk()
	buildCPU()
	buildRom()
}

type SuperComputer struct {
	Name string
}

func (this *SuperComputer) buildDisk() {
	fmt.Println("超大硬盘")
}

func (this *SuperComputer) buildCPU() {
	fmt.Println("超快CPU")
}

func (this *SuperComputer) buildRom() {
	fmt.Println("超大内存")
}

// ------------

type LowComputer struct {
	Name string
}

func (this *LowComputer) buildDisk() {
	fmt.Println("超小硬盘")
}

func (this *LowComputer) buildCPU() {
	fmt.Println("超慢CPU")
}

func (this *LowComputer) buildRom() {
	fmt.Println("超小内存")
}

type Drictor struct {
	builder Builder
}

func NewConstruct(b Builder) *Drictor {
	return &Drictor{
		builder: b,
	}
}

func (this *Drictor) Consturct() {
	this.builder.buildDisk()
	this.builder.buildCPU()
	this.builder.buildRom()
}

func main() {
	sc := SuperComputer{}
	d := NewConstruct(&sc)
	d.Consturct()

	fmt.Println("--------------")

	lc := LowComputer{}
	d2 := NewConstruct(&lc)
	d2.Consturct()
}

java中建造者模式的实现
public class House {
    private String foundation;
    private String structure;
    private String roof;
    private String interior;

    public House() {
    }

    public String getFoundation() {
        return foundation;
    }

    public void setFoundation(String foundation) {
        this.foundation = foundation;
    }

    public String getStructure() {
        return structure;
    }

    public void setStructure(String structure) {
        this.structure = structure;
    }

    public String getRoof() {
        return roof;
    }

    public void setRoof(String roof) {
        this.roof = roof;
    }

    public String getInterior() {
        return interior;
    }

    public void setInterior(String interior) {
        this.interior = interior;
    }

}

public interface HouseBuilder {
    void buildFoundation();

    void buildStructure();

    void buildRoof();

    void buildInterior();

    House getHouse();
}

public class BasicHouseBuilder implements HouseBuilder {
    private House house;

    public BasicHouseBuilder() {
        house = new House();
    }

    @Override
    public void buildFoundation() {
        house.setFoundation("Basic Foundation");
    }

    @Override
    public void buildStructure() {
        house.setStructure("Basic Structure");
    }

    @Override
    public void buildRoof() {
        house.setRoof("Basic Roof");
    }

    @Override
    public void buildInterior() {
        house.setInterior("Basic Interior");
    }

    @Override
    public House getHouse() {
        return house;
    }
}

public class Director {
    private HouseBuilder houseBuilder;

    public Director(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }

    public void constructHouse() {
        houseBuilder.buildFoundation();
        houseBuilder.buildStructure();
        houseBuilder.buildRoof();

golang 原型模式(包含深浅拷贝的讨论

原型模式用于创建重复的对象,当一个类在创建四开销比较大的时候(如大量的数据准备或者数据库的连接),我们可以缓存该对象,当下一次调用的时候,返回该对象的克隆
用原型实例指定创建该对象的种类,并且通过拷贝这些原型创建的新对象,通过克隆操作clone(),快速的生成和原型对象一样的实例。
请添加图片描述

package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
)

type CPU struct {
	Name string
}

type ROM struct {
	Name string
}

type Disk struct {
	Name string
}

type Computer struct {
	Cpu  CPU
	Rom  ROM
	Disk Disk
}

func (s *Computer) Clone() *Computer {
	resume := *s
	return &resume
}

func (s *Computer) BackUp() *Computer {
	pc := new(Computer)
	if err := deepCopy(pc, s); err != nil {
		panic(err.Error())
	}
	return pc
}

func deepCopy(dst, src interface{}) error {
	var buf bytes.Buffer
	if err := gob.NewEncoder(&buf).Encode(src); err != nil {
		return err
	}
	return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}

func main() {
	cpu := CPU{"奔腾586"}
	rom := ROM{"金士顿"}
	disk := Disk{"三星"}

	c := Computer{
		Cpu:  cpu,
		Rom:  rom,
		Disk: disk,
	}

	c1 := c.BackUp()
	fmt.Printf("c1: %v\n", *c1)

}

深浅拷贝:


func (s Computer) clone1() *Computer {/*这是一个浅拷贝*/
	resume := &s
	return resume

}

func (s *Computer) Clone() *Computer {/*这是一个深拷贝*/
	resume := *s
	return &resume
}

······这两段代码尝试将 computer 类型的实例进行克隆(创建一个副本)。它们的区别在于第一段代码中的 clone1() 方法返回的是 s 的指针,而第二段代码中的 clone() 方法返回的是 resume 的指针。

从计算机底层存储结构的角度来看,第一段代码中的 clone1() 方法的作用是将 s 的地址存储到名为 resume 的指针变量中。因此,对 resume 进行操作会影响到原始对象 s。

相比之下,第二段代码中的 clone() 方法使用了解引用操作符——*,以获取 s 所指向内存地址上的值。然后,创建一个名为 resume 的新变量并将其初始化为获取到的值。这个新变量与 s 不同,并且位于另一个内存地址上。最后,该方法返回的是 resume 的指针,即指向所创建的新赋值对象的指针。

因此,第一段代码使用起来存在潜在风险,因为对 resume 所指向的内存地址进行的所有操作都会影响到原始对象 s,而第二段代码中的 clone() 方法则更加安全,因为它在内存中复制了一份与原始对象完全**的副本。······

java中原型模式的应用:

// 定义一个实现Cloneable接口的抽象原型类
public abstract class Shape implements Cloneable {
    private String id;
    protected String type;

    public String getType() {
        return type;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    // 定义clone方法
    public abstract Shape clone();
}


// 定义扩展自抽象原型类的具体类型
public class Circle extends Shape {

    public Circle(){
        type = "Circle";
    }

    @Override
    public Shape clone() {
        Circle circle = null;
        try {
            circle = (Circle) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return circle;
    }
}


// 定义一个原型管理器,用于存储和获取原型对象
public class ShapeCache {
    private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();

    public static Shape getShape(String shapeId) {
        Shape cachedShape = shapeMap.get(shapeId);
        return (Shape) cachedShape.clone();
    }

    // 对每个具体类型的应用程序,都需要在原型管理器中添加相应的原型对象
    public static void loadCache() {
        Circle circle = new Circle();
        circle.setId("1");
        shapeMap.put(circle.getId(), circle);
    }
}


// 使用原型模式创建新的对象
public class PrototypePatternDemo {
    public static void main(String[] args) {
        ShapeCache.loadCache();

        Shape clonedShape = (Shape) ShapeCache.getShape("1");
        System.out.println("Shape : " + clonedShape.getType());        
    }
}

golang适配器模式

适配器模式是作为来个互不兼容的俩个接口之间的桥梁,适配器模式市是将一个累的接口转换为令一个类的接口,是的原本由于接口兼容而不能在一起工作的类可以在一起工作。
请添加图片描述

package main

import "fmt"

type OldInterface interface {
	OldMethod()
}

type OldImpl struct {
}

func (OldImpl) OldMethod() {
	fmt.Println("旧方法实现")
}

type NewInterface interface {
	NewMethod()
}

type Adapter struct {
	OldInterface
}

// 适配器
func (a *Adapter) NewMethod() {
	fmt.Println("新方法实现")
	a.OldMethod()
}

func main() {
	oldInteface := OldImpl{}
	a := Adapter{OldInterface: oldInteface}
	a.NewMethod()
}

用java实现适配器模式的例子:

类适配器:
首先创建一个目标接口,他是客户端代码调用的接口:

public interface MediaPlayer {
    public void play(String audioType, String fileName);
}

然后创建一个媒体播放器的实现类:

public class AudioPlayer implements MediaPlayer {

   @Override
   public void play(String audioType, String fileName) {
   
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: " + fileName);         
      } 
      
      else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")){
         MediaAdapter mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      
      else{
         System.out.println("Invalid media. " + audioType + " format not supported");
      }
   }   
}

这里的AudioPlayer可以播放MP3格式的文件,但不支持VLC和MP4格式的文件,为了能让这个类能够支持更多形式的格式,需要使用适配器模式:

public class MediaAdapter implements MediaPlayer {

   AdvancedMediaPlayer advancedMusicPlayer;

   public MediaAdapter(String audioType){
   
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();       
      }
      else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }

   @Override
   public void play(String audioType, String fileName) {
   
      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }
      else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}

这个适配器类实现了目标接口,并且包含一个先进的媒体播放器(AdvancedMediaPlayer)

Golang桥接模式:

桥接是用于把抽象化与现实化解耦,使得俩者可以独立变化,这种类型的设计模式属于是结构型模式,他通过提供抽象画与现实化的桥接结构,来实现二者的解耦
这种模式涉及到一个作为桥接的接口 ,使得实现类的功能独立于接口实现类,这俩中结构的类可以被结构化改变但是互不影响。
请添加图片描述
实例:
我们使用DrawAPI作为桥接模式的抽象接口,shapeCircle作为桥接模式的实体类,将抽象接口保存在实体类中,使得抽象接口实例变化时,shapeCircle可以始终不变。

package main

import "fmt"

//DrawAPI 画图抽象接口,桥接模式的抽象接口
type DrawAPI interface {
	DrawCircle(radius, x, y int)
}

//RedCircle 红色圆的类,桥接模式接口
type RedCircle struct{}

//NewRedCircle 实例化红色圆
func NewRedCircle() *RedCircle {
	return &RedCircle{}
}

//DrawCircle 红色圆实现DrawAPI方法
func (rc *RedCircle) DrawCircle(radius, x, y int) {
	fmt.Printf("Drawing Circle[ color: red, radius: %d, x: %d, y: %d ]\n", radius, x, y)
}

//GreenCircle 绿色圆的实体类,桥接模式接口
type GreenCircle struct{}

//NewGreenCircle 实例化绿色圆
func NewGreenCircle() *GreenCircle {
	return &GreenCircle{}
}

//DrawCircle 绿色圆实现DrawAPI方法
func (gc *GreenCircle) DrawCircle(radius, x, y int) {
	fmt.Printf("Drawing Circle[ color: green, radius: %d, x: %d, y: %d ]\n", radius, x, y)
}

//ShapeCircle 桥接模式的实体类
type ShapeCircle struct {
	Radius  int
	X       int
	Y       int
	drawAPI DrawAPI
}

//NewShapeCircle 实例化桥接模式实体类
func NewShapeCircle(radius, x, y int, drawAPI DrawAPI) *ShapeCircle {
	return &ShapeCircle{
		Radius:  radius,
		X:       x,
		Y:       y,
		drawAPI: drawAPI,
	}
}

//Draw 实体类的Draw方法
func (sc *ShapeCircle) Draw() {
	sc.drawAPI.DrawCircle(sc.Radius, sc.X, sc.Y)
}

func main() {
	redCircle := NewShapeCircle(5, 6, 8, NewRedCircle())
	redCircle.Draw()

	greenCircle := NewShapeCircle(1, 2, 4, NewGreenCircle())
	greenCircle.Draw()

}

java实现桥接模式的例子:

public interface Shape {
    void draw();
}
public class Circle implements Shape {
    private int x, y, radius;
    private DrawAPI drawAPI;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.drawAPI = drawAPI;
    }

    public void draw() {
        drawAPI.drawCircle(radius, x, y);
    }
}

public class Rectangle implements Shape {
    private int x, y, width, height;
    private DrawAPI drawAPI;

    public Rectangle(int x, int y, int width, int height, DrawAPI drawAPI) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.drawAPI = drawAPI;
    }

    public void draw() {
        drawAPI.drawRectangle(x, y, width, height);
    }
}
public interface DrawAPI {
    void drawCircle(int radius, int x, int y);
    void drawRectangle(int x, int y, int width, int height);
}

public class RedCircle implements DrawAPI {
    public void drawCircle(int radius, int x, int y) {
        System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", y: " + y + "]");
    }
}

public class GreenRectangle implements DrawAPI {
    public void drawRectangle(int x, int y, int width, int height) {
        System.out.println("Drawing Rectangle[ color: green, x: " + x + ", y: " + y + ", width: " + width + ", height: " + height + "]");
    }
}
public class BridgePatternDemo {
    public static void main(String[] args) {
        Shape redCircle = new Circle(100,100, 10, new RedCircle());
        Shape greenRectangle = new Rectangle(50,50,100,100, new GreenRectangle());

        redCircle.draw();
        greenRectangle.draw();
    }
}
/*通过使用 Bridge 模式,我们可以将 Shape 和 DrawAPI 两个层次结构独立地进行修改和扩展,而不会影响到彼此。这种解耦的方式可以使得代码更加灵活和可维护。*/

golang装饰器模式:

装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。
装饰器模式创建了一个装饰类,。用来包装原有类,并且在保持类方法签名完整的前提下,提供了额外的功能。
请添加图片描述

package main

import "fmt"

//Shape 模型接口
type Shape interface {
	Draw()
}

//Circle 圆形类
type Circle struct{}

//NewCircle 实例化圆形
func NewCircle() *Circle {
	return &Circle{}
}

//Draw 输出方法,实现Shape接口
func (c *Circle) Draw() {
	fmt.Println("画圆方法")
}

//RedShapeDecorator 红色装饰器
type RedShapeDecorator struct {
	DecoratedShape Shape
}

//NewRedShapeDecorator 实例化红色装饰器
func NewRedShapeDecorator(decShape Shape) *RedShapeDecorator {
	return &RedShapeDecorator{
		DecoratedShape: decShape,
	}
}

//SetRedBorder 装饰器方法
func (rs *RedShapeDecorator) SetRedBorder() {
	fmt.Println("红色边框")
}

//Draw 实现Shape接口的方法
func (rs *RedShapeDecorator) Draw() {
	rs.DecoratedShape.Draw()
	rs.SetRedBorder()
}

func main() {
	c := NewCircle()
	rsd := NewRedShapeDecorator(c)
	rsd.Draw()
}

java实现装饰器模式:

// 创建一个接口,定义要被装饰的对象的基本行为
interface StringOperation {
    String operate(String input);
}

// 创建一个具体的实现类,实现上述接口
class StringEncryptor implements StringOperation {
    @Override
    public String operate(String input) {
        // 实现对字符串的加密操作
        return input + " [encrypted]";
    }
}

// 创建一个装饰器类,实现上述接口,并包含一个内部成员变量,类型为上述接口
class StringDecorator implements StringOperation {
    private StringOperation operation;

    // 在装饰器类中,定义一个构造函数,用于接收上述接口的实例,并将其赋值给内部成员变量
    public StringDecorator(StringOperation operation) {
        this.operation = operation;
    }

    // 在装饰器类中,实现上述接口的方法,并在方法中调用内部成员变量的对应方法,以实现基本行为的增强
    @Override
    public String operate(String input) {
        String output = operation.operate(input);
        // 实现对字符串的解密操作
        return output.replace(" [encrypted]", " [decrypted]");
    }
}

// 使用装饰器模式对字符串进行加密和解密
public class DecoratorPatternDemo {
    public static void main(String[] args) {
        StringOperation operation = new StringEncryptor();
        operation = new StringDecorator(operation);

        String input = "Hello, world!";
        String output = operation.operate(input);

        System.out.println("Input: " + input);
        System.out.println("Output: " + output);
    }
}

Golang组合模式

组合模式,又叫做部分整体模式,用于把一组一组的对象当做单一的对象
组合模式将对象组合形成树形结构,以表示整体部分的层次结构。使得用户对单个对象的使用具有一致性
请添加图片描述

package main

import (
	"container/list"
	"fmt"
	"reflect"
	"strconv"
)

//Employee 职员类
type Employee struct {
	Name         string
	Dept         string
	Salary       int
	Subordinates *list.List
}

//NewEmployee 实例化职员类
func NewEmployee(name, dept string, salary int) *Employee {
	sub := list.New()
	return &Employee{
		Name:         name,
		Dept:         dept,
		Salary:       salary,
		Subordinates: sub,
	}
}

//Add 添加职员的下属
func (e *Employee) Add(emp Employee) {
	e.Subordinates.PushBack(emp)
}

//Remove 删除职员的下属
func (e *Employee) Remove(emp Employee) {
	for i := e.Subordinates.Front(); i != nil; i = i.Next() {
		if reflect.DeepEqual(i.Value, emp) {
			e.Subordinates.Remove(i)
		}
	}
}

//GetSubordinates 获取职员下属列表
func (e *Employee) GetSubordinates() *list.List {
	return e.Subordinates
}

//ToString 获取职员的string信息
func (e *Employee) ToString() string {
	return "[ Name: " + e.Name + ", dept: " + e.Dept + ", Salary: " + strconv.Itoa(e.Salary) + " ]"
}

func main() {

	ceo := NewEmployee("老李", "ceo", 9999)

	pm := NewEmployee("ceo下属张三", "技术", 1000)
	programmer1 := NewEmployee("张三下属李四", "技术", 8000)
	programmer2 := NewEmployee("张三下属王五", "技术", 8000)

	minister := NewEmployee("ceo下属赵六", "财务", 5000)

	finance1 := NewEmployee("赵六下属陈七", "财务", 3000)
	finance2 := NewEmployee("赵六下属牛八", "财务", 2900)

	ceo.Add(*pm)
	ceo.Add(*minister)

	pm.Add(*programmer1)
	pm.Add(*programmer2)

	minister.Add(*finance1)
	minister.Add(*finance2)

	//打印所有职员
	fmt.Println(ceo.ToString())

	fmt.Println("####################")

	for i := ceo.Subordinates.Front(); i != nil; i = i.Next() {
		em := i.Value.(Employee)
		fmt.Println(em.ToString())
		fmt.Println("************************")
		for j := i.Value.(Employee).Subordinates.Front(); j != nil; j = j.Next() {
			em := j.Value.(Employee)
			fmt.Println(em.ToString())
		}
		fmt.Println("----------------")
	}
}

组合模式的java对比

import java.util.ArrayList;
import java.util.List;

// 抽象类或接口,定义组件的共同行为
interface Component {
    void operation();
}

// 叶子节点类
class Leaf implements Component {
    @Override
    public void operation() {
        System.out.println("执行叶子节点操作");
    }
}

// 组合节点类,包含了多个子组件
class Composite implements Component {
    private List<Component> components = new ArrayList<>();

    public void add(Component component) {
        components.add(component);
    }

    public void remove(Component component) {
        components.remove(component);
    }

    @Override
    public void operation() {
        System.out.println("执行组合节点操作");

        for (Component component : components) {
            component.operation();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建组件对象
        Component leaf1 = new Leaf();
        Component leaf2 = new Leaf();

        Composite composite1 = new Composite();
        composite1.add(leaf1);

        Composite composite2 = new Composite();
        composite2.add(leaf2);
        composite2.add(composite1);

        // 调用组合节点的操作(会执行自身操作,以及子节点的操作)
        composite2.operation();
    }
}

}

golang实现外观模式

外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问的接口

外观模式为子系统中的一组接口提供一个一致性的画面,这个接口是的这个子系统更加容易使用
请添加图片描述
本实例演示了一个运动场馆,可以提供打篮球和踢足球的运动的实力,类似于这样的案例还有很多,例如 医院挂号系统,公司门卫等

package main

import "fmt"

type Sport interface {
	Run()
}

type Basketball struct {
}
type Football struct {
}
//创建了篮球和足球的实例化对象
func NewBasketball() *Basketball {
	return &Basketball{}
}

func NewFootball() *Football {
	return &Football{}
}
//以足球和篮球为接受者实现run方法
func (*Basketball) Run() {
	fmt.Println("打篮球")
}

func (*Football) Run() {
	fmt.Println("踢足球")
}

type SportFacade struct {
	basketball Basketball
	football   Football
}

func NewSportFacade() *SportFacade {
	return &SportFacade{
		basketball: Basketball{},
		football:   Football{},
	}
}

func (f *SportFacade) PlayBasketball() {
	f.basketball.Run()
}

func (f *SportFacade) PlayFootball() {
	f.football.Run()
}

func main() {
	sf := NewSportFacade()
	sf.PlayBasketball()
	sf.PlayFootball()
}

java实现外观模式的例子

首先,我们需要创建一个外观类来封装子系统中的复杂逻辑,在本例中,我们将创建一个shapeMaker类作为外观类

public class ShapeMaker {
   private Shape rectangle;
   private Shape circle;
   private Shape square;

   public ShapeMaker() {
      rectangle = new Rectangle();
      circle = new Circle();
      square = new Square();
   }

   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawCircle(){
      circle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

然后,我们需要定义几个形状类(Shape class),以及这些类的具体实现,例如Rectangle、Circle和Square。

public interface Shape {
   void draw();
}

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}

最后,我们可以通过调用ShapeMaker类中的方法简单地绘制各种形状,而无需了解它们的具体实现。

public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();

      shapeMaker.drawRectangle();
      shapeMaker.drawCircle();
      shapeMaker.drawSquare();        
   }
}

golang实现享元模式

享元模式主要用于减少创建对象的数量,以减少内存占用,提高性能。
享元模式尝试重用现有的同类对象,如果为找到匹配的对象,则创建新的对象。
请添加图片描述

package main

import "fmt"

//Shape 模型接口
type Shape interface {
	Draw()
}

//Circle 圆形类
type Circle struct {
	X      int
	Y      int
	Radius int
	Color  string
}

//NewCircle 实例化圆形类
func NewCircle(color string) *Circle {
	return &Circle{
		Color: color,
	}
}

//SetX 设置圆形类的x轴
func (c *Circle) SetX(x int) {
	c.X = x
}

//SetY 设置圆形类的y轴
func (c *Circle) SetY(y int) {
	c.Y = y
}

//SetRadius 设置圆形类的半径
func (c *Circle) SetRadius(radius int) {
	c.Radius = radius
}

//Draw 圆形类的Draw方法,实现Shape接口
func (c *Circle) Draw() {
	fmt.Printf("绘制圆 [颜色: %s, x: %d, y: %d, 半径: %d] \n",
		c.Color,
		c.X,
		c.Y,
		c.Radius)
}

//ShapeFactory 模型工厂类,包含一个circle的map
type ShapeFactory struct {
	circleMap map[string]Shape
}

//NewShapeFactory 实例化模型工厂类
func NewShapeFactory() *ShapeFactory {
	return &ShapeFactory{
		circleMap: make(map[string]Shape),
	}
}

//GetCircle 获取一个圆形实例
//color: 需要获取实例的颜色
func (sf *ShapeFactory) GetCircle(color string) Shape {
	circle := sf.circleMap[color]
	// 核心享元思想 (没有再创建)
	if circle == nil {
		circle = NewCircle(color)
		sf.circleMap[color] = circle
		fmt.Println("创建圆的颜色: ", color)
	}
	return circle
}

func main() {
	sf := NewShapeFactory()
	sf.GetCircle("red").Draw()
	sf.GetCircle("red").Draw()
	sf.GetCircle("green").Draw()
	sf.GetCircle("green").Draw()
	sf.GetCircle("blue").Draw()
	sf.GetCircle("blue").Draw()

	// 我们发现Circle被创建了三次,而不是六次
}

java实现享元模式的例子:

import java.util.HashMap;

interface Shape {
    void draw();
}

class Circle implements Shape {
    private String color;
    private int x;
    private int y;
    private int radius;

    public Circle(String color) {
        this.color = color;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing circle with color " + color + ", x = " + x + ", y = " + y + ", and radius = " + radius);
    }
}

class ShapeFactory {
    private static final HashMap<String, Circle> circles = new HashMap<>();

    public static Circle getCircle(String color) {
        Circle circle = circles.get(color);

        if (circle == null) {
            circle = new Circle(color);
            circles.put(color, circle);
            System.out.println("Creating circle of color " + color);
        }

        return circle;
    }
}

public class FlyweightPatternExample {
    private static final String[] COLORS = { "red", "green", "blue" };

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            Circle circle = ShapeFactory.getCircle(COLORS[(int)(Math.random() * COLORS.length)]);

            circle.setX((int)(Math.random() * 100));
            circle.setY((int)(Math.random() * 100));
            circle.setRadius((int)(Math.random() * 10));

            circle.draw();
        }
    }
}
/*Shape 接口是享元的基类。
Circle 类实现了 Shape 接口。它具有颜色、x 坐标、y 坐标和半径等属性,而且会在绘制时输出这些属性的值。
ShapeFactory 类是工厂类,负责创建并管理共享的 Circle 对象
*/

golang实现代理模式

代理模式中,一个类代表另一个类的功能
代理模式为其他对象提供一种代理,以控制对这个对象的访问。
请添加图片描述

package main

import "fmt"

type Subject interface {
	Do()
}

type RealSubject struct {
}

func (rs *RealSubject) Do() {
	fmt.Println("do something...")
}

type Proxy struct {
	RealSubject
}

func (p *Proxy) Do() {
	fmt.Println("代理在之前要做的事情,例如:日志、安全处理")
	p.RealSubject.Do()
	fmt.Println("代理在之后要做的事情,例如:日志、安全处理")
}

// aop 实现机制

func main() {
	real := RealSubject{}
	proxy := Proxy{real}
	proxy.Do()
}

aop(面向切面编程)是一种编程范式,允许程序员捕获和修改程序执行流程中的某些特定点。aop通过将这些特定点称为“切入点”,并针对每个切入点定义称为“通知”的功能模块来实现此目的。

实现aop的机制大体分为以下三类:

  1. 静态代理:在编译时期生成代理类, 通过代理类来包装原始对象,从而实现切入点织入。静态代理需要手动创建代理类,在复杂项目中不太适用。

  2. 动态代理:在运行时借助反射机制动态生成代理类。java提供了两种接口实现动态代理:jdk自带的java.lang.reflect.proxy 和第三方库cglib。

    • java动态代理(jdk proxy):动态创建代理类,要求被代理对象实现接口或至少有一个实现接口的父类,并且通过invocationhandler对方法进行拦截。缺点是只能代理有实现接口的类,若没有使用到接口,则无法代理。

    • cglib: 对无接口的类也可以生成代理。cglib采用了基于asm的字节码技术,通过继承和重载方式,动态生成代理子类,子类通过方法***回调机制,拦截被代理对象的方法并执行相应通知逻辑。

  3. 字节码增强:通过对类字节码进行修改,在加载时动态地将切面织入原始类中。常用的工具有aspectj和javassist等。字节码增强可实现更加灵活的切入点,但也更加复杂,并且可能会影响系统性能。==

golang模板方法设计模式

模板方法设计模式定义了一个算法的步骤,并允许子类,为一个或者多个步骤提供其实践方式,让子类在不改变算法框架的前提下,重新定义算法中的某些步骤
请添加图片描述
比如,人都是一样的有出生和去世,但是中间这个工程是不同的,成功人士生活的好,不成功的人士生活的不好。

package main

import "fmt"

type IPerson interface {
	Birth()    // 出生
	Live()     // 生活
	Dead()     // 死亡
	LifeTime() // 一生 模板方法
}

type Person struct {
}

func (p *Person) Birth() {
	fmt.Println("出生..")
}

func (p *Person) Live() {
	// 空着等具体类实现
}

func (p *Person) Dead() {
	fmt.Println("离开..")
}

func (p *Person) LifeTime() {
	p.Birth()
	p.Live()
	p.Dead()
}

type SuccessPerson struct {
	Person
}

type FailPerson struct {
	Person
}

func (p *SuccessPerson) Live() {
	// 空着等具体类实现
	fmt.Println("成功人士活得好")
}

func (p *SuccessPerson) LifeTime() {
	p.Birth()
	p.Live()
	p.Dead()
}

func (p *FailPerson) Live() {
	// 空着等具体类实现
	fmt.Println("失败人士活得差")
}

func (p *FailPerson) LifeTime() {
	p.Birth()
	p.Live()
	p.Dead()
}

func main() {
	p := Person{}
	sp := SuccessPerson{p}
	fp := FailPerson{p}

	sp.LifeTime()

	fp.LifeTime()
}

golang命令模式

命令模式是一种数据驱动的设计模式,属于行为性模式。请求以命令的模式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
请添加图片描述
实例:

package main

import (
	"container/list"
	"fmt"
)

//Order 订单命令接口
type Order interface {
	Execute()
}

//Stock 股票类
type Stock struct {
	Name     string
	Quantity int
}

//NewStock 实例化一只股票
func NewStock() *Stock {
	return &Stock{
		Name:     "茅台",
		Quantity: 1000,
	}
}

//Buy 股票的买方法
func (s *Stock) Buy() {
	fmt.Printf("股票 [ 名称: %s, 数量: %d ] 买.\n",
		s.Name,
		s.Quantity)
}

//Sell 股票的卖方法
func (s *Stock) Sell() {
	fmt.Printf("股票 [ 名称: %s, 数量: %d ] 卖.\n",
		s.Name,
		s.Quantity)
}

//BuyStock 买股票类,实现了Order接口的订单类
type BuyStock struct {
	StockToBy Stock
}

//NewBuyStock 实例化买股票订单类
func NewBuyStock(st Stock) *BuyStock {
	return &BuyStock{
		StockToBy: st,
	}
}

//Execute 处理买股票订单
func (bs *BuyStock) Execute() {
	bs.StockToBy.Buy()
}

//SellStock 卖股票类,实现了Order接口的订单类
type SellStock struct {
	StockToSell Stock
}

//NewSellStock 实例化卖股票订单类
func NewSellStock(st Stock) *SellStock {
	return &SellStock{
		StockToSell: st,
	}
}

//Execute 处理卖股票订单
func (ss *SellStock) Execute() {
	ss.StockToSell.Sell()
}

//Broker 创建命令调用类
type Broker struct {
	OrderList *list.List
}

//NewBroker 实例化命令调用类
func NewBroker() *Broker {
	return &Broker{
		OrderList: list.New(),
	}
}

//TakeOrder 添加命令
func (b *Broker) TakeOrder(order Order) {
	b.OrderList.PushBack(order)
}

//PlaceOrders 处理命令
func (b *Broker) PlaceOrders() {
	for i := b.OrderList.Front(); i != nil; {
		//处理完一个指令,就将该指令删除
		nextOrder := i.Next()
		i.Value.(Order).Execute()
		b.OrderList.Remove(i)
		i = nextOrder
	}
}

func main() {
	maotaiStock := NewStock()

	buyStockOrder := NewBuyStock(*maotaiStock)
	sellStockOrder := NewSellStock(*maotaiStock)

	broker := NewBroker()
	broker.TakeOrder(buyStockOrder)
	broker.TakeOrder(sellStockOrder)

	broker.PlaceOrders()
}

golang实现迭代器模式

迭代器模式用于顺序访问集合中元素
迭代器提供一种方法顺序访问一个对象的二哥哥元素,而无须暴露对象内部的表示。
请添加图片描述

package main

import "fmt"

type Order struct {
	Name string
}

type OrderList struct {
	Orders []Order
}

func NewOrderList() *OrderList {

	orders := make([]Order, 0)
	return &OrderList{
		orders,
	}

}

func (ol *OrderList) GetIterator() func() (Order, bool) {
	index := 0
	return func() (order Order, ok bool) {
		if index >= len(ol.Orders) {
			return
		}
		order, ok = ol.Orders[index], true
		index++
		return
	}
}

// 添加
func (ol *OrderList) Add(order Order) {
	ol.Orders = append(ol.Orders, order)
}

func main() {

	ol := NewOrderList()
	o1 := Order{"book"}
	o2 := Order{"clothes"}
	ol.Add(o1)
	ol.Add(o2)

	it := ol.GetIterator()

	for {
		order, ok := it()
		if !ok {
			break
		}
		fmt.Println("Order: ", order.Name)
	}

}

golang实现观察者模式

定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主体对象,当主体对象发生变化时,他的所有依赖者都会收到通知并更新,这种模式有事又称为发布订阅模式,模型视图模式,他是对象行为型模式
例如,微信公众号和粉丝之间的发布和订阅
请添加图片描述
请添加图片描述

package main

import (
	"fmt"
)

// 读者(观察者)
type Reader interface {
	// 更新方法
	Update()
}

// 读者1
type Reader1 struct {
	subject *Subject
}

func (b *Reader1) Reader1Observer(subject *Subject) {
	b.subject = subject
	b.subject.Attach(b)
}

func (b *Reader1) Update() {
	fmt.Println("读者1: ", b.subject.GetState())
}

// 读者2
type Reader2 struct {
	subject *Subject
}

func (o *Reader2) Reader2Observer(subject *Subject) {
	o.subject = subject
	o.subject.Attach(o)
}

func (o *Reader2) Update() {
	fmt.Println("读者2:", o.subject.GetState())
}

// 读者3
type Reader3 struct {
	subject *Subject
}

func (h *Reader3) Reader3Observer(subject *Subject) {
	h.subject = subject
	h.subject.Attach(h)
}

func (h *Reader3) Update() {
	fmt.Println("读者3:", h.subject.GetState())
}

// 主题
type Subject struct {
	// 观察者列表
	readers []Reader
	state   int
}

func NewSubject() *Subject {
	return &Subject{
		state:   0,
		readers: make([]Reader, 0),
	}
}

// 获得状态
func (s *Subject) GetState() int {
	return s.state
}

// 设置状态
func (s *Subject) SetState(state int) {
	s.state = state
	s.NotifyAllObservers()
}

// 添加观察者
func (s *Subject) Attach(observer Reader) {
	s.readers = append(s.readers, observer)
}

// 通知所有观察者
func (s *Subject) NotifyAllObservers() {
	for _, observer := range s.readers {
		observer.Update()
	}
}

func main() {
	subject := NewSubject()

	reader1 := Reader1{subject: subject}
	reader2 := Reader2{subject: subject}
	reader3 := Reader3{subject: subject}

	subject.Attach(&reader1)
	subject.Attach(&reader2)
	subject.Attach(&reader3)

	subject.SetState(1)
	subject.SetState(2)

}

golang中介者模式

在这里插入图片描述
请添加图片描述

package main

import (
	"fmt"
	"time"
)

// 联合国
type UnitedNations struct {
}

var un = NewUnitedNations()

// 创建联合国
func NewUnitedNations() *UnitedNations {
	return &UnitedNations{}
}

// 联合国显示各个国家发来的消息
func (un *UnitedNations) ShowMessage(nation *Nation, msg string) {
	fmt.Printf("%s: [ %s ]: %s \n",
		time.Now().Format("2006-01-02 15:04:05"),
		nation.Name,
		msg)
}

// 其他国家
type Nation struct {
	Name string
}

// new
func NewNation(name string) *Nation {
	return &Nation{name}
}

// SendMessage 各个国家向联合国发消息
func (n *Nation) SendMessage(msg string) {
	un.ShowMessage(n, msg)
}

func main() {

	n1 := NewNation("中国")
	n1.SendMessage("我要强大...")

	n2 := NewNation("美国")
	n2.SendMessage("我要看看谁不服...")
}

golang实现备忘录模式

备忘录模式保存对象的一个状态,以便在适合的时间回复对象
备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并且在对象之外保存这个状态,这样可以在以后将这个对恢复到原先保存的状态

例如:
编辑器的本地历史,游戏存档,ctrl+z ,数据库事务都是这种模式
请添加图片描述

package main

import "fmt"

//Memento 备忘录类
type Memento struct {
	state string
}

//NewMemento 实例化备忘录类
func NewMemento(st string) *Memento {
	return &Memento{
		state: st,
	}
}

//GetState 获取备忘录类的状态
func (m *Memento) GetState() string {
	return m.state
}

//Originator 初始类
type Originator struct {
	state string
}

//NewOriginator 实例化初始类
func NewOriginator(st string) *Originator {
	return &Originator{
		state: st,
	}
}

//SetState 初始化类设置状态
func (o *Originator) SetState(st string) {
	o.state = st
}

//GetState 从初始类中获取状态
func (o *Originator) GetState() string {
	return o.state
}

//SaveStateToMemento 将初始类状态保存到备忘录类
func (o *Originator) SaveStateToMemento() *Memento {
	return NewMemento(o.state)
}

//GetStateFromMemento 将备忘录类的状态读取到初始类
func (o *Originator) GetStateFromMemento(memento *Memento) {
	o.state = memento.GetState()
}

//CareTaker 保存类,用于存储备忘录实例
type CareTaker struct {
	MementoList map[int]*Memento
}

//NewCareTaker 实例化保存类
func NewCareTaker() *CareTaker {
	return &CareTaker{
		MementoList: make(map[int]*Memento),
	}
}

//Add 保存类添加备忘录实例
func (ct *CareTaker) Add(index int, memento *Memento) {
	ct.MementoList[index] = memento
}

//Get 保存类获取备忘录实例
func (ct *CareTaker) Get(index int) *Memento {
	return ct.MementoList[index]
}

func main() {
	careTaker := NewCareTaker()
	originator := NewOriginator("状态 #1")
	originator.SetState("状态 #2")
	careTaker.Add(1, originator.SaveStateToMemento())
	originator.SetState("状态 #3")
	careTaker.Add(2, originator.SaveStateToMemento())
	originator.SetState("状态 #4")

	fmt.Println("当前状态:", originator.GetState())
	originator.GetStateFromMemento(careTaker.Get(1))
	fmt.Println("第一次保存状态:", originator.GetState())
	originator.GetStateFromMemento(careTaker.Get(2))
	fmt.Println("第二次保存状态:", originator.GetState())
}

golang实现解释器模式

解释器模式提供了评估语言和语法表达式的方式
解释器模式实现了一个表达式的接口,该接口解释一个特定的上下文,这种模式被用在例如:sql语句处理,符号解释引擎等
请添加图片描述

package main

import (
	"fmt"
	"strings"
)

//Expression 语句接口
type Expression interface {
	Interpret(context string) bool
}

//TerminalExpression 终端语句类
type TerminalExpression struct {
	Data string
}

//NewTerminalExpression 实例化终端语句类
func NewTerminal *TerminalExpression {
	return &TerminalExpression{
		Data: data,
	}
}

//Interpret 终端语句类的解释器
func (te *TerminalExpression) Interpret(context string) bool {
	if strings.Contains(context, te.Data) {
		return true
	}
	return false
}

//OrExpression 或语句类
type OrExpression struct {
	Expr1 Expression
	Expr2 Expression
}

//NewOrExpression 实例化或语句
func NewOr *OrExpression {
	return &OrExpression{
		Expr1: expr1,
		Expr2: expr2,
	}
}

//Interpret 解释器
func (oe *OrExpression) Interpret(context string) bool {
	return oe.Expr1.Interpret(context) || oe.Expr2.Interpret(context)
}

//AndExpression 与语句类
type AndExpression struct {
	Expr1 Expression
	Expr2 Expression
}

//NewAndExpression 实例化与语句
func NewAnd *AndExpression {
	return &AndExpression{
		Expr1: expr1,
		Expr2: expr2,
	}
}

//Interpret 解释器
func (ae *AndExpression) Interpret(context string) bool {
	return ae.Expr1.Interpret(context) && ae.Expr2.Interpret(context)
}

func main() {

	// or
	lee := NewTerminal
	wang := NewTerminal
	isMale := NewOr

	b := isMale.Interpret("Lee")
	fmt.Printf("b: %v\n", b)
	fmt.Println("--------")

	// and

	yang := NewTerminal
	married := NewTerminal
	isMarried := NewAnd

	b2 := isMarried.Interpret("Married Yang")
	fmt.Printf("b2: %v\n", b2)

}

golang实现状态模式

状态模式中,类的行为是基于他的状态改变的
状态模式中允许对象在内部改变状态时,改变他的行为,这样对象看起来好像是修改了它的类。
请添加图片描述

package main

import "fmt"

//Context 状态保存 类
type Context struct {
	state State
}

//NewContext 实例化状态保存类
func NewContext() *Context {
	return &Context{
		state: nil,
	}
}

//SetState 设置状态保存类当前的状态
func (c *Context) SetState(s State) {
	c.state = s
}

//GetState 获取状态保存类当前的状态
func (c *Context) GetState() State {
	return c.state
}

//State 状态接口
type State interface {
	DoAction(context *Context)
	ToString() string
}

//StartState 开始状态类
type StartState struct{}

//NewStartState 实例化开始状态类
func NewStartState() *StartState {
	return &StartState{}
}

//DoAction 开始状态类的DoAction,实现State接口
func (start *StartState) DoAction(context *Context) {
	fmt.Println("现在是开始状态")
	context.state = start
}

//ToString 返回开始状态类名称
func (start *StartState) ToString() string {
	return "开始状态"
}

//StopState 停止状态类
type StopState struct{}

//NewStopState 实例化停止状态类
func NewStopState() *StopState {
	return &StopState{}
}

//DoAction 停止状态类方法,实现State接口
func (stop *StopState) DoAction(context *Context) {
	fmt.Println("现在是停止状态")
	context.state = stop
}

//ToString 返回停止状态类名称
func (stop *StopState) ToString() string {
	return "停止状态"
}

func main() {
	context := NewContext()

	startState := NewStartState()
	startState.DoAction(context)
	fmt.Println(context.GetState().ToString())
	fmt.Println("-------------")
	stopState := NewStopState()
	stopState.DoAction(context)
	fmt.Println(context.GetState().ToString())
}

golang实现策略模式

策略模式,一个类的行为或者其算法可以在运行时改变
策略模式定义一系列算法,把他们一个一个封装起来,并且可以使他相互替换请添加图片描述
实例:
下面演示图书打折实例,把每种打折算法都封装起来,并抽象其接口,客户端只依赖接口。

package main

import "fmt"

// 打折接口
type IDiscount interface {
	Discount() float32
}

type Book struct {
	Price float32
}

func (b *Book) GetPrice(d IDiscount) float32 {
	return b.Price * d.Discount()
}

type Discount85 struct {
}

func (d *Discount85) Discount() float32 {
	return 0.85
}

type Discount65 struct {
}

func (d *Discount65) Discount() float32 {
	return 0.65
}

func main() {

	b := Book{100}
	d65 := Discount65{}
	p := b.GetPrice(&d65)
	fmt.Printf("p: %v\n", p)
	fmt.Println("-------")
	d85 := Discount85{}
	p = b.GetPrice(&d85)
	fmt.Printf("p: %v\n", p)

}

golang实现责任链模式

Chain of Responsibility Pattern为请求创建一个接受者对象的链,这样可以使得请求和发送者解耦。
为了避免请求者和发送者耦合在一起,让多个对象都有可能接收数据,我们将这些对象连成一个链,并且沿着这条链传递请求,直到有对象处理这个请求为止。
请添加图片描述

package main

import "fmt"

const (
	//StandardLogLevel 标准日志等级
	StandardLogLevel = iota
	//InfoLogLevel info日志等级
	InfoLogLevel
	//ErrorLogLevel 错误日志等级
	ErrorLogLevel
)

//BaseLogger 日志接口
type BaseLogger interface {
	PrintLog(level int, message string)
	Write(message string)
}

//StandardLogger 标准日志类
type StandardLogger struct {
	Level      int
	NextLogger BaseLogger
}

//NewStandardLogger 实例化标准日志类
func NewStandardLogger() *StandardLogger {
	return &StandardLogger{
		Level:      StandardLogLevel,
		NextLogger: nil,
	}
}

//Write 标准日志类写日志方法
func (sl *StandardLogger) Write(message string) {
	fmt.Printf("标准日志输出: %s.\n", message)
}

//PrintLog 标准日志类输入日志,并且流向下一个对象方法
func (sl *StandardLogger) PrintLog(level int, message string) {
	if sl.Level == level {
		sl.Write(message)
	}
	if sl.NextLogger != nil {
		sl.NextLogger.PrintLog(level, message)
	}
}

//SetNextLogger 标准日志类设置下一个对象方法
func (sl *StandardLogger) SetNextLogger(logger BaseLogger) {
	sl.NextLogger = logger
}

//InfoLogger 提示日志类
type InfoLogger struct {
	Level      int
	NextLogger BaseLogger
}

//NewInfoLogger 实例化提示日志类
func NewInfoLogger() *InfoLogger {
	return &InfoLogger{
		Level:      InfoLogLevel,
		NextLogger: nil,
	}
}

//Write 提示日志类的写方法
func (infoL *InfoLogger) Write(message string) {
	fmt.Printf("信息日志输出: %s.\n", message)
}

//PrintLog 提示日志类的输入日志方法
func (infoL *InfoLogger) PrintLog(level int, message string) {
	if infoL.Level == level {
		infoL.Write(message)
	}
	if infoL.NextLogger != nil {
		infoL.NextLogger.PrintLog(level, message)
	}
}

//SetNextLogger 提示日志类设置下一个对象
func (infoL *InfoLogger) SetNextLogger(logger BaseLogger) {
	infoL.NextLogger = logger
}

//ErrorLogger 错误日志类
type ErrorLogger struct {
	Level      int
	NextLogger BaseLogger
}

//NewErrorLogger 实例化错误日志类
func NewErrorLogger() *ErrorLogger {
	return &ErrorLogger{
		Level:      ErrorLogLevel,
		NextLogger: nil,
	}
}

//Write 错误日志类写方法
func (el *ErrorLogger) Write(message string) {
	fmt.Printf("错误日志输出: %s.\n", message)
}

//PrintLog 错误日志类输入日志方法
func (el *ErrorLogger) PrintLog(level int, message string) {
	if el.Level == level {
		el.Write(message)
	}
	if el.NextLogger != nil {
		el.NextLogger.PrintLog(level, message)
	}
}

//SetNextLogger 错误日志类设置下一个对象
func (el *ErrorLogger) SetNextLogger(logger BaseLogger) {
	el.NextLogger = logger
}

//GetChainOfLoggers 获取日志对象链
func GetChainOfLoggers() BaseLogger {
	errLog := NewErrorLogger()
	infoLog := NewInfoLogger()
	standardLog := NewStandardLogger()

	errLog.SetNextLogger(infoLog)
	infoLog.SetNextLogger(standardLog)

	return errLog
}

func main() {
	logChain := GetChainOfLoggers()
	logChain.PrintLog(InfoLogLevel, "这是一条信息")
	logChain.PrintLog(StandardLogLevel, "这是标准输出")
	logChain.PrintLog(ErrorLogLevel, "这是错误信息")
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊啊啊杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值