时间: 2020-09-03 00:08:26 人气: 2304 评论: 0
design pattern 介绍设计模式
engineer pattern 总结先进的工程模式
参考
对golang来说就是Newxx函数,返回interface, kubernetes interface随处可见,可以说能用interface抽象的就是interface,随便举一个例子
// k8s.io/kubernetes/vendor/k8s.io/client-go/tools/cache/store.go func NewStore(keyFunc KeyFunc) Store { return &cache{ cacheStorage: NewThreadSafeStore(Indexers{}, Indices{}), keyFunc: keyFunc, } } type cache struct { // cacheStorage bears the burden of thread safety for the cache cacheStorage ThreadSafeStore // keyFunc is used to make the key for objects stored in and retrieved from items, and // should be deterministic. keyFunc KeyFunc } type Store interface { Add(obj interface{}) error Update(obj interface{}) error Delete(obj interface{}) error List() []interface{} ListKeys() []string Get(obj interface{}) (item interface{}, exists bool, err error) GetByKey(key string) (item interface{}, exists bool, err error) // Replace will delete the contents of the store, using instead the // given list. Store takes ownership of the list, you should not reference // it after calling this function. Replace([]interface{}, string) error Resync() error }
组合模式的不同形式,这些随处可见,也不用深究其中的区别。
kubernetes/golang 用得很少,一般使用全局变量(如配置) (比如 net/http package 的 http.DefaultClient 和 http.DefaultServeMux). 或者作为context传递。
实现方式可以参考http://marcio.io/2015/07/singleton-pattern-in-go/
比较常见的一种方式是double check
func GetInstance() *singleton { if instance == nil { // <-- Not yet perfect. since it's not fully atomic mu.Lock() defer mu.Unlock() if instance == nil { instance = &singleton{} } } return instance }
但是在golang里面有更好的一种方式,用"Once"
type singleton struct { } var instance *singleton var once sync.Once func GetInstance() *singleton { once.Do(func() { instance = &singleton{} }) return instance }
关于这几种creational patterns 的区别:
factory
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/serializer/codec_factory.go func NewCodecFactory(scheme *runtime.Scheme) CodecFactory { serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory) return newCodecFactory(scheme, serializers) } func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec { return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner) }
abstract factory 以SharedInformerFactory为例,这个factory 能够create app/core/batch ...等各种interface
//k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/factory.go func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory { return &sharedInformerFactory{ client: client, defaultResync: defaultResync, informers: make(map[reflect.Type]cache.SharedIndexInformer), startedInformers: make(map[reflect.Type]bool), } } // SharedInformerFactory provides shared informers for resources in all known // API group versions. type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool Admissionregistration() admissionregistration.Interface Apps() apps.Interface Autoscaling() autoscaling.Interface Batch() batch.Interface Certificates() certificates.Interface Core() core.Interface Extensions() extensions.Interface Networking() networking.Interface Policy() policy.Interface Rbac() rbac.Interface Scheduling() scheduling.Interface Settings() settings.Interface Storage() storage.Interface } // sharedInformerFactory 是具体的stuct func (f *sharedInformerFactory) Apps() apps.Interface { return apps.New(f) }
builder
// k8s.io/kubernetes/pkg/controller/client_builder.go func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.admissionregistrationV1alpha1 = admissionregistrationv1alpha1.NewForConfigOrDie(c) cs.appsV1beta1 = appsv1beta1.NewForConfigOrDie(c) cs.appsV1beta2 = appsv1beta2.NewForConfigOrDie(c) cs.appsV1 = appsv1.NewForConfigOrDie(c) cs.authenticationV1 = authenticationv1.NewForConfigOrDie(c) cs.authenticationV1beta1 = authenticationv1beta1.NewForConfigOrDie(c) cs.authorizationV1 = authorizationv1.NewForConfigOrDie(c) cs.authorizationV1beta1 = authorizationv1beta1.NewForConfigOrDie(c) cs.autoscalingV1 = autoscalingv1.NewForConfigOrDie(c) cs.autoscalingV2beta1 = autoscalingv2beta1.NewForConfigOrDie(c) cs.batchV1 = batchv1.NewForConfigOrDie(c) cs.batchV1beta1 = batchv1beta1.NewForConfigOrDie(c) cs.batchV2alpha1 = batchv2alpha1.NewForConfigOrDie(c) cs.certificatesV1beta1 = certificatesv1beta1.NewForConfigOrDie(c) cs.coreV1 = corev1.NewForConfigOrDie(c) cs.extensionsV1beta1 = extensionsv1beta1.NewForConfigOrDie(c) cs.networkingV1 = networkingv1.NewForConfigOrDie(c) cs.policyV1beta1 = policyv1beta1.NewForConfigOrDie(c) cs.rbacV1 = rbacv1.NewForConfigOrDie(c) cs.rbacV1beta1 = rbacv1beta1.NewForConfigOrDie(c) cs.rbacV1alpha1 = rbacv1alpha1.NewForConfigOrDie(c) cs.schedulingV1alpha1 = schedulingv1alpha1.NewForConfigOrDie(c) cs.settingsV1alpha1 = settingsv1alpha1.NewForConfigOrDie(c) cs.storageV1beta1 = storagev1beta1.NewForConfigOrDie(c) cs.storageV1 = storagev1.NewForConfigOrDie(c) cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) return &cs }
原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
The Prototype Pattern creates duplicate objects while keeping performance in mind. It's a part of the creational patterns and provides one of the best ways to create an object.
参考http://blog.ralch.com/tutorial/design-patterns/golang-prototype/
kubernetes使用了deepcopy-gen自动生成对象的deepcopy等方法,比如下面的一个生成的例子
// k8s.io/kubernetes/vendor/k8s.io/apiserver/pkg/apis/audit/zz_generated.deepcopy.go // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GroupResources) DeepCopyInto(out *GroupResources) { *out = *in if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = make([]string, len(*in)) copy(*out, *in) } if in.ResourceNames != nil { in, out := &in.ResourceNames, &out.ResourceNames *out = make([]string, len(*in)) copy(*out, *in) } return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupResources. func (in *GroupResources) DeepCopy() *GroupResources { if in == nil { return nil } out := new(GroupResources) in.DeepCopyInto(out) return out }
生成的工具在这里 k8s.io/kubernetes/vendor/k8s.io/co