golang 享元模式

一、定义

运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

二、理解

在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题。比如,在围棋中的白子和黑子,各个对象很相似,如果为每一个对象都重新生成一个对象,会造成资源的浪费。享元模式就是将大量对象共有的部分抽取出来,供这些对象共享使用。而这些元素不同的部分,会以参数的形式注入具体享元的相关方法中。
在享元模式中,有以下几种角色:

  1. 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  2. 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
  3. 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
  4. 享元工厂(Flyweight
    Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

三、代码示例

棋子中分为白子(具体享元)和黑子(具体享元),它们有自己独有的信息,在棋盘上会有许多棋子,它们的位置不同(非享元)。
可以看到,虽然我们”下了“200个棋子,实际上,我们只用了两个棋子元素(享元),而位置(非共享信息)以参数的形式注入具体享元的相关方法中即xiaqi
i在实际应用中,我们简单打印的白子和黑子的信息可能是许多内容,通过这种方式,节约了资源。每一次只需创建对象的非共享信息即可。
java:

public class Flyweight {
    //享元模式:享元工厂(ChessFactory)、抽象享元(Chess、下棋的方法,需要传入一个位置),具体享元(WhiteChess、BlackChess),非共享角色PositonInfo,
    public static void main(String[] args) {

        //获取黑子与白子
        Chess black = ChessFactory.getChess(CHESS_COLOR.BLACK);
        Chess white = ChessFactory.getChess(CHESS_COLOR.WHITE);

        for (int i = 0; i < 100; i++) {
            PositionInfo info = new PositionInfo(i,i);
            black.xiaQi(info);
            white.xiaQi(info);
        }
        //可以看到,虽然我们”下了“200个棋子,实际上,我们只用了两个棋子元素(享元),而位置(非共享信息)以参数的形式注入具体享元的相关方法中即xiaqi
        //在实际应用中,我们简单打印的白子和黑子的信息可能是许多内容,通过这种方式,节约了资源。每一次只需创建对象的非共享信息即可。
    }
}

class PositionInfo {
    public Integer x;
    public Integer y;
    public PositionInfo(Integer x,Integer y){
        this.x= x;
        this.y = y;
    }
}

interface Chess {
    void xiaQi(PositionInfo positionInfo);
}

class BlackChess implements Chess {

    public String info;

    @Override
    public void xiaQi(PositionInfo positionInfo) {
        System.out.println("下黑子,位置:"+positionInfo.x+"," + positionInfo.y);
        System.out.println("棋子的信息:"+this.info);
    }
}

class White implements Chess {
    public String info;

    @Override
    public void xiaQi(PositionInfo positionInfo) {
        System.out.println("下白子,位置:"+positionInfo.x+"," + positionInfo.y);
        System.out.println("棋子的信息:"+this.info);
    }
}

enum CHESS_COLOR {
    BLACK, WHITE
}

class ChessFactory {
    private static Map<CHESS_COLOR,Chess> chessList = new HashMap<>();

    static {
        BlackChess black = new BlackChess();
        black.info= "所有黑棋共有的信息";
        chessList.put(CHESS_COLOR.BLACK,black);
        White white = new White();
        white.info = "所有白棋共有的信息";
        chessList.put(CHESS_COLOR.WHITE,white);
    }

    public static Chess getChess(CHESS_COLOR color) {
       return  chessList.get(color);
    }
}

golang:

func main() {
	factory := NewChessFactory()
	blackChess := factory.GetChess(BLACK)
	whiteChess := factory.GetChess(WHITE)

	for i := 0; i < 100; i++ {
		positionInfo := new(PositionInfo)
		positionInfo.X ,positionInfo.Y= i,i
		blackChess.XiaQi(positionInfo)
		whiteChess.XiaQi(positionInfo)
	}
}

//非享元信息类
type PositionInfo struct {
	X int
	Y int
}

//享元接口类
type Chess interface {
	XiaQi(positionInfo *PositionInfo)
}

type BlackChess struct {
	Info string
}

func (chess *BlackChess) XiaQi(info *PositionInfo)  {
	fmt.Println("下黑子,位置:",info.X,",",info.Y)
	fmt.Println("棋子的信息",chess.Info)
}

type WhiteChess struct {
	Info string
}

func (chess *WhiteChess) XiaQi(info *PositionInfo)  {
	fmt.Println("下黑子,位置:",info.X,",",info.Y)
	fmt.Println("棋子的信息",chess.Info)
}

type CHESS_COLOR uint8
const (
	BLACK CHESS_COLOR= 0
	WHITE CHESS_COLOR= 1
)

//享元模式工厂类
type ChessFactory struct {
	m map[CHESS_COLOR]Chess
}

//棋子工厂,单例模式
var once sync.Once
var chessFactory *ChessFactory;

func NewChessFactory() *ChessFactory {
	once.Do(func() {
		chessFactory = new(ChessFactory)
		chessFactory.m = make(map[CHESS_COLOR]Chess,2)
		blackChess := new(BlackChess)
		blackChess.Info = "所有黑棋共有的信息"
		chessFactory.m[BLACK] =blackChess
		whiteCHess := new(WhiteChess)
		whiteCHess.Info = "所有白棋共有的信息"
		chessFactory.m [WHITE]=whiteCHess
	})
	return chessFactory
}

func (factory *ChessFactory) GetChess(color CHESS_COLOR) Chess {
	return factory.m[color]
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而无需暴露对象创建的逻辑。在 Golang 中,可以使用工厂函数来实现工厂模式。工厂函数是一个返回接口类型的函数,该接口表示所需对象的抽象类型。具体的对象类型由工厂函数内部的逻辑决定。以下是一个使用 Golang 实现工厂模式的示例代码: ``` package main import "fmt" type Product interface { GetName() string } type ConcreteProductA struct{} func (p *ConcreteProductA) GetName() string { return "Product A" } type ConcreteProductB struct{} func (p *ConcreteProductB) GetName() string { return "Product B" } func CreateProduct(productType string) Product { switch productType { case "A": return &ConcreteProductA{} case "B": return &ConcreteProductB{} default: return nil } } func main() { productA := CreateProduct("A") fmt.Println(productA.GetName()) productB := CreateProduct("B") fmt.Println(productB.GetName()) } ``` 在上面的示例代码中,我们定义了一个 `Product` 接口和两个具体的产品类型 `ConcreteProductA` 和 `ConcreteProductB`。我们还定义了一个 `CreateProduct` 工厂函数,该函数根据传入的参数返回不同的产品类型。在 `main` 函数中,我们使用 `CreateProduct` 函数创建了两个不同的产品,并调用了它们的 `GetName` 方法。 这就是使用 Golang 实现工厂模式的基本方法。 ### 回答2: 工厂模式是一种创建对象的设计模式,其目的是将对象的创建与使用分离,以便在需要时根据不同的条件和参数创建不同的对象。使用Golang编写工厂模式可以按照以下步骤进行: 1. 首先,创建一个接口,定义所需对象的方法和属性。 ```go type Product interface { GetName() string SetName(name string) GetPrice() float64 } ``` 2. 然后,创建多个结构体类型,实现该接口。每个结构体代表一个具体的产品。 ```go type TV struct { name string price float64 } func (t *TV) GetName() string { return t.name } func (t *TV) SetName(name string) { t.name = name } func (t *TV) GetPrice() float64 { return t.price } type Computer struct { name string price float64 } func (c *Computer) GetName() string { return c.name } func (c *Computer) SetName(name string) { c.name = name } func (c *Computer) GetPrice() float64 { return c.price } ``` 3. 创建一个工厂函数,根据传入的参数返回对应的对象实例。 ```go func CreateProduct(productType string) Product { switch productType { case "TV": return &TV{} case "Computer": return &Computer{} default: return nil } } ``` 4. 在主函数中调用工厂函数创建具体的产品对象。 ```go func main() { tv := CreateProduct("TV") tv.SetName("Samsung TV") tv.GetPrice() computer := CreateProduct("Computer") computer.SetName("Lenovo Computer") computer.GetPrice() } ``` 通过以上步骤,我们可以使用Golang编写一个简单的工厂模式,根据需要创建不同类型的产品对象。这种模式可以将创建对象的细节封装起来,并提供统一的接口来使用不同的产品。 ### 回答3: 工厂模式是一种创建对象的设计模式,通过定义一个统一的接口和工厂方法,来创建不同类型的对象。在golang中,可以使用结构体和接口的方式实现工厂模式。 首先,我们定义一个接口,用于表示要创建的对象: ```go type Product interface { Name() string Price() float64 } ``` 然后,我们创建多个结构体类型实现该接口,每个结构体类型表示一种具体的产品: ```go type ProductA struct {} func (a *ProductA) Name() string { return "ProductA" } func (a *ProductA) Price() float64 { return 10.0 } type ProductB struct {} func (b *ProductB) Name() string { return "ProductB" } func (b *ProductB) Price() float64 { return 20.0 } ``` 接下来,我们定义一个工厂结构体,用于创建不同类型的产品对象: ```go type ProductFactory struct {} func (f *ProductFactory) CreateProduct(productType string) Product { switch productType { case "A": return &ProductA{} case "B": return &ProductB{} default: return nil } } ``` 最后,我们可以通过调用工厂的CreateProduct方法来创建不同类型的产品对象: ```go func main() { factory := &ProductFactory{} productA := factory.CreateProduct("A") fmt.Println(productA.Name(), productA.Price()) productB := factory.CreateProduct("B") fmt.Println(productB.Name(), productB.Price()) } ``` 以上就是使用golang写工厂模式的简单示例。使用工厂模式可以封装对象的创建逻辑,使得客户端程序与具体产品的实现解耦。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值