func WithEventDispatcher(eventDispatcher event.Dispatcher) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.eventDispatcher = eventDispatcher
	}
}
WithEventDispatcher sets event dispatcher on the factory.
package client
import (
	"context"
	"errors"
	"time"
	"github.com/optimizely/go-sdk/pkg/config"
	"github.com/optimizely/go-sdk/pkg/decide"
	"github.com/optimizely/go-sdk/pkg/decision"
	"github.com/optimizely/go-sdk/pkg/event"
	"github.com/optimizely/go-sdk/pkg/logging"
	"github.com/optimizely/go-sdk/pkg/metrics"
	"github.com/optimizely/go-sdk/pkg/registry"
	"github.com/optimizely/go-sdk/pkg/utils"
)
type OptimizelyFactory struct {
	SDKKey              string
	Datafile            []byte
	DatafileAccessToken string
	configManager        config.ProjectConfigManager
	ctx                  context.Context
	decisionService      decision.Service
	defaultDecideOptions *decide.Options
	eventDispatcher      event.Dispatcher
	eventProcessor       event.Processor
	userProfileService   decision.UserProfileService
	overrideStore        decision.ExperimentOverrideStore
	metricsRegistry      metrics.Registry
}
type OptionFunc func(*OptimizelyFactory)
func (f *OptimizelyFactory) Client(clientOptions ...OptionFunc) (*OptimizelyClient, error) {
	for _, opt := range clientOptions {
		opt(f)
	}
	if f.SDKKey == "" && f.Datafile == nil && f.configManager == nil {
		return nil, errors.New("unable to instantiate client: no project config manager, SDK key, or a Datafile provided")
	}
	var metricsRegistry metrics.Registry
	if f.metricsRegistry != nil {
		metricsRegistry = f.metricsRegistry
	} else {
		metricsRegistry = metrics.NewNoopRegistry()
	}
	var ctx context.Context
	if f.ctx != nil {
		ctx = f.ctx
	} else {
		ctx = context.Background()
	}
	var decideOptions *decide.Options
	if f.defaultDecideOptions != nil {
		decideOptions = f.defaultDecideOptions
	} else {
		decideOptions = &decide.Options{}
	}
	eg := utils.NewExecGroup(ctx, logging.GetLogger(f.SDKKey, "ExecGroup"))
	appClient := &OptimizelyClient{
		defaultDecideOptions: decideOptions,
		execGroup:            eg,
		notificationCenter:   registry.GetNotificationCenter(f.SDKKey),
		logger:               logging.GetLogger(f.SDKKey, "OptimizelyClient"),
	}
	if f.configManager != nil {
		appClient.ConfigManager = f.configManager
	} else {
		appClient.ConfigManager = config.NewPollingProjectConfigManager(
			f.SDKKey,
			config.WithInitialDatafile(f.Datafile),
			config.WithDatafileAccessToken(f.DatafileAccessToken),
		)
	}
	if f.eventProcessor != nil {
		appClient.EventProcessor = f.eventProcessor
	} else {
		var eventProcessorOptions = []event.BPOptionConfig{
			event.WithSDKKey(f.SDKKey),
		}
		if f.eventDispatcher != nil {
			eventProcessorOptions = append(eventProcessorOptions, event.WithEventDispatcher(f.eventDispatcher))
		}
		eventProcessorOptions = append(eventProcessorOptions, event.WithEventDispatcherMetrics(metricsRegistry))
		appClient.EventProcessor = event.NewBatchEventProcessor(eventProcessorOptions...)
	}
	if f.decisionService != nil {
		appClient.DecisionService = f.decisionService
	} else {
		var experimentServiceOptions []decision.CESOptionFunc
		if f.userProfileService != nil {
			experimentServiceOptions = append(experimentServiceOptions, decision.WithUserProfileService(f.userProfileService))
		}
		if f.overrideStore != nil {
			experimentServiceOptions = append(experimentServiceOptions, decision.WithOverrideStore(f.overrideStore))
		}
		compositeExperimentService := decision.NewCompositeExperimentService(f.SDKKey, experimentServiceOptions...)
		compositeService := decision.NewCompositeService(f.SDKKey, decision.WithCompositeExperimentService(compositeExperimentService))
		appClient.DecisionService = compositeService
	}
	if pollingConfigManager, ok := appClient.ConfigManager.(*config.PollingProjectConfigManager); ok {
		eg.Go(pollingConfigManager.Start)
	}
	if batchProcessor, ok := appClient.EventProcessor.(*event.BatchEventProcessor); ok {
		eg.Go(batchProcessor.Start)
	}
	return appClient, nil
}
func WithDatafileAccessToken(datafileAccessToken string) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.DatafileAccessToken = datafileAccessToken
	}
}
func WithPollingConfigManager(pollingInterval time.Duration, initDataFile []byte) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.configManager = config.NewPollingProjectConfigManager(f.SDKKey, config.WithInitialDatafile(initDataFile),
			config.WithPollingInterval(pollingInterval))
	}
}
func WithPollingConfigManagerDatafileAccessToken(pollingInterval time.Duration, initDataFile []byte, datafileAccessToken string) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.configManager = config.NewPollingProjectConfigManager(f.SDKKey, config.WithInitialDatafile(initDataFile),
			config.WithPollingInterval(pollingInterval), config.WithDatafileAccessToken(datafileAccessToken))
	}
}
func WithConfigManager(configManager config.ProjectConfigManager) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.configManager = configManager
	}
}
func WithDecisionService(decisionService decision.Service) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.decisionService = decisionService
	}
}
func WithDefaultDecideOptions(decideOptions []decide.OptimizelyDecideOptions) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.defaultDecideOptions = convertDecideOptions(decideOptions)
	}
}
func WithUserProfileService(userProfileService decision.UserProfileService) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.userProfileService = userProfileService
	}
}
func WithExperimentOverrides(overrideStore decision.ExperimentOverrideStore) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.overrideStore = overrideStore
	}
}
func WithBatchEventProcessor(batchSize, queueSize int, flushInterval time.Duration) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.eventProcessor = event.NewBatchEventProcessor(event.WithBatchSize(batchSize),
			event.WithQueueSize(queueSize), event.WithFlushInterval(flushInterval))
	}
}
func WithEventProcessor(eventProcessor event.Processor) OptionFunc {
	return func(f *OptimizelyFactory) {
		f.eventProcessor = eventProcessor
	}
}