Home > Back-end >  Is this right for a factory method producing singletons?
Is this right for a factory method producing singletons?

Time:11-19

I've got this bit of code for a factory method to produce singletons. I have a small MAUI app and want to have persistent global data.

public static class FactoryService
{
    private static BudgetViewModel budgetViewModelInstance;
    private static AccountsViewModel accountsViewModelInstance;
    private static PayeesViewModel payeesViewModelInstance;

    public static BaseViewModel BuildViewModel(Type type)
    {
        if(type == typeof(BudgetViewModel))
        {
            budgetViewModelInstance ??= new BudgetViewModel();
            return budgetViewModelInstance;
        }
        else if(type == typeof(AccountsViewModel))
        {
            accountsViewModelInstance ??= new AccountsViewModel();
            return accountsViewModelInstance;
        }
        else if(type == typeof(PayeesViewModel))
        {
            payeesViewModelInstance ??= new PayeesViewModel();
            return payeesViewModelInstance;
        }
        else
        {
            throw new Exception($"Can't build View Model. Invalid View Model: {type}");
        }
    }
}

Then when I want a view model reference, I have to cast the type I want before calling BuildViewModel:

BudgetViewModel budgetViewModel = (BudgetViewModel)FactoryService.BuildViewModel(typeof(BudgetViewModel));

Is this.... right? Is there a better way to accomplish this? I can't use static classes for the view models because they have to inherit from ObservableObject. (from the Community MVVM Toolkit)

CodePudding user response:

I would use generics. Something like this:

public static class FactoryService
{
    private static BudgetViewModel budgetViewModelInstance;
    private static AccountsViewModel accountsViewModelInstance;
    private static PayeesViewModel payeesViewModelInstance;
    private static readonly object _lock = new object();

    public static T BuildViewModel<T>() where T : BaseViewModel, new()
    {
        if (typeof(T) == typeof(BudgetViewModel))
        {
            if (budgetViewModelInstance == null)
            {
                lock (_lock)
                {
                    if (budgetViewModelInstance == null)
                    {
                        budgetViewModelInstance = new();
                    }
                }
            }

            return budgetViewModelInstance as T;
        }
        else if (typeof(T) == typeof(AccountsViewModel))
        {
            if (accountsViewModelInstance == null)
            {
                lock (_lock)
                {
                    if (accountsViewModelInstance == null)
                    {
                        accountsViewModelInstance = new();
                    }
                }
            }

            return accountsViewModelInstance as T;
        }
        else if (typeof(T) == typeof(PayeesViewModel))
        {
            if (payeesViewModelInstance == null)
            {
                lock (_lock)
                {
                    if (payeesViewModelInstance == null)
                    {
                        payeesViewModelInstance = new();
                    }
                }
            }

            return payeesViewModelInstance as T;
        }
        else
        {
            throw new Exception($"Can't build View Model. Invalid View Model: {typeof(T)}");
        }
    }
}

Then you can invoke like this: var viewModel = FactoryService.BuildViewModel<BudgetViewModel>();

  • Related