四、原型模式

 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有的实例来创建新的对象,而不是通过构造新对象的方式。原型模式是通过克隆一个已存在对象(即原型)来实现对象的快速创建。

主要组成部分:

  1. 原型接口(Prototype)

    • 定义一个用于克隆自身的接口,通常包含一个 clone 方法。
  2. 具体原型(Concrete Prototype)

    • 实现原型接口的具体类,提供详细的克隆逻辑。
  3. 客户端(Client)

    • 使用原型对象来创建新的对象实例。

优点:

  1. 性能:通过克隆现有的对象,可以快速创建新对象,特别是当对象创建过程复杂时,可以显著提高性能。

  2. 创建为简单:不需要关注对象的具体构造过程,降低了对象创建的复杂性。

  3. 动态性:原型模式支持运行时动态创建对象,允许通过不同的原型实例来创建新对象。

缺点:

  1. 复杂性:实现深拷贝和浅拷贝逻辑可能会变得复杂。需要确保对象的状态在克隆时能够正确复制。

  2. 依赖:需要原型类保存所有可能用于创建对象的状态,可能会导致设计上的复杂性。

GO:

  • 这个模式在 Java、C++ 这种面向对象的语言不太常用,但是如果大家使用过 javascript 的话就会非常熟悉了,因为 js 本身是基于原型的面向对象语言,所以原型模式在 js 中应用非常广泛。
  • 需求: 假设现在数据库中有大量数据,包含了关键词,关键词被搜索的次数等信息,模块 A 为了业务需要
    • 会在启动时加载这部分数据到内存中
    • 并且需要定时更新里面的数据
    • 同时展示给用户的数据每次必须要是相同版本的数据,不能一部分数据来自版本 1 一部分来自版本 2
package prototype

import (
	"encoding/json"
	"time"
)

// Keyword 搜索关键字
type Keyword struct {
	word      string
	visit     int
	UpdatedAt *time.Time
}

// Clone 这里使用序列化与反序列化的方式深拷贝
func (k *Keyword) Clone() *Keyword {
	var newKeyword Keyword
	b, _ := json.Marshal(k)
	err := json.Unmarshal(b, &newKeyword)
	if err != nil {
		return nil
	}
	return &newKeyword
}

// Keywords 关键字 map
type Keywords map[string]*Keyword

// Clone 复制一个新的 keywords
// updatedWords: 需要更新的关键词列表,由于从数据库中获取数据常常是数组的方式
func (words Keywords) Clone(updatedWords []*Keyword) Keywords {
	newKeywords := Keywords{}

	for k, v := range words {
		// 这里是浅拷贝,直接拷贝了地址
		newKeywords[k] = v
	}

	// 替换掉需要更新的字段,这里用的是深拷贝
	for _, word := range updatedWords {
		newKeywords[word.word] = word.Clone()
	}
	return newKeywords
}
package prototype

import (
	"github.com/stretchr/testify/assert"
	"testing"
	"time"
)

func TestKeywords_Clone(t *testing.T) {
	updateAt, _ := time.Parse("2006", "2020")
	words := Keywords{
		"testA": &Keyword{
			word:      "testA",
			visit:     1,
			UpdatedAt: &updateAt,
		},
		"testB": &Keyword{
			word:      "testB",
			visit:     2,
			UpdatedAt: &updateAt,
		},
		"testC": &Keyword{
			word:      "testC",
			visit:     3,
			UpdatedAt: &updateAt,
		},
	}

	now := time.Now()
	updatedWords := []*Keyword{
		{
			word:      "testB",
			visit:     10,
			UpdatedAt: &now,
		},
	}

	got := words.Clone(updatedWords)

	assert.Equal(t, words["testA"], got["testA"])
	assert.NotEqual(t, words["testB"], got["testB"])
	assert.NotEqual(t, updatedWords[0], got["testB"])
	assert.Equal(t, words["testC"], got["testC"])
}

JAVA:

// 原型接口
public interface Prototype {
    Prototype clone();
}
// 具体原型类
public class ConcretePrototype implements Prototype{
    private String field;

    public ConcretePrototype(String field) {
        this.field = field;
    }

    public String getField() {
        return field;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototype(this.field);
    }
}
@Test(description = "原型模式")
    public void prototypeTest(){
        // 创建一个对象
        ConcretePrototype prototype = new ConcretePrototype("Original");

        //通过克隆来创建对象
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();

        // 输出原型和克隆对象的字段
        System.out.println("Prototype Field: " + prototype.getField()); // 输出: Original
        System.out.println("Cloned Field: " + clone.getField()); // 输出: Original

        // 修改克隆对象的字段
        // 因为是深拷贝,这里要重新设定克隆对象的字段
        clone = new ConcretePrototype("Cloned");
        System.out.println("Cloned Field After Modification: " + clone.getField()); // 输出: Cloned
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值