Какой шаблон можно использовать для создания объекта одного класса, но заполнять его свойства разными способами? - PullRequest
0 голосов
/ 10 октября 2019

У меня есть такой класс

public class OwnerWithholding
    {

        private decimal ManagementFeePct;

        private decimal TotalManagementFee;

        private decimal OperationalFeesPct;

        private decimal TotalOperationalFees;

}

И у меня есть метод вычисления, который создает объект этого класса, заполняет его некоторыми арифметическими операциями и возвращает этот объект.

public OwnerWithholding CalculationMethod1(Reservation r, SqlConnection conn)
        {
            OwnerWithholding result = new OwnerWithholding();

           // result.ManagementFeePct  = some data from Fees table in DB + value 
           //from another db - constant value..

           // Also with other properties - with some operations on data

           //result.TotalManagementFee = ..
           // result.OperationalFeesPct = ..
           // result. TotalOperationalFees = ..

            return result;
        }

А теперь работает нормально. Но этот метод расчета является лишь одним из вариантов заполнения данных.

Существует еще один метод расчета, реализованный совершенно по-другому, но заполняющий точно такие же свойства объекта. И у меня их может быть больше.

Мне нужен шаблон, который позволил бы мне создавать объекты того же класса, просто указав необходимый метод расчета. Мне нравится шаблон стратегии, где алгоритмами будут методы, которые заполняют объекты, которые их вызвали. Но это выглядит не очень хорошо. Может быть, фабричный метод был бы более уместным здесь, но я не знаю, как его реализовать.

1 Ответ

1 голос
/ 10 октября 2019

Редактировать : Теперь, следуя комментариям ОП, похоже, что ОДИН метод в классе должен быть установлен несколькими способами. Шаблонный шаблон (или Строитель) лучше подходит для этого случая, а не для Фабрики.

Шаблон шаблона.

a. Абстрактный Базовый класс, который устанавливает свойства по умолчанию, но оставляет одно свойство (Get Ingredients) для заполнения конкретными классами.

    public abstract class PizzaCreator
    {
        public abstract string GetIngredients { get; }
        public string Bake { get; set; } = "Bake at 400F for 30 minutes";
        public string Deliver { get; set; } = "Deliver in custom box";
    }

b. Два класса Pizza, на данный момент просто переопределяя абстрактное свойство

    public class CheesePizza : PizzaCreator
    {
        public override string GetIngredients
        {
            get { return GetMyIngredients(); }
        }

        string GetMyIngredients()
        {
            return "Lots of Cheese!";
        }
    }

    public class PepperoniPizza : PizzaCreator
    {
        public override string GetIngredients
        {
            get { return GetMyIngredients(); }
        }

        string GetMyIngredients()
        {
            return "Lots of Meats!";
        }
    }

Здесь я создаю экземпляры Pizza

            var pepPizza = new PepperoniPizza();
            var chessePizza = new CheesePizza();

Вы можете даже направить эти создания черезФабричный класс / метод.

Оригинальный ответ : Вот абстрактный шаблон Фабрики.

Этот код входит в библиотеку классов Фабрики.

a.ICar интерфейс

    public interface ICar
    {
        string Name { get; set; }
        int Doors { get; set; }
        string EngineCapacity { get; set; }
    }

b.Abstract Автозавод

    public abstract class AbstractCarFactory
    {
        public abstract ICar CreateCar(CarType type);
    }

c. Два бетонных вагона -

    internal class NissanPickUpTruck : ICar
    {
        public string Name { get; set; } 
        public int Doors { get; set ; }
        public string EngineCapacity { get ; set ; }
    }

    internal class NissanSportsCar: ICar
    {
        public string Name { get; set; } 
        public int Doors { get; set; }
        public string EngineCapacity { get; set; }
    }

d. Бетонный завод

    public class NissanFactory : AbstractCarFactory
    {
        public override ICar CreateCar(CarType type)
        {
            switch (type)
            {
                case CarType.PickupTruck:
                    return new NissanPickUpTruck{Name = "Titan", Doors = 6, EngineCapacity = "V12"};
                case CarType.SportsCar:
                    return new NissanSportsCar{Name = "350Z", Doors = 2, EngineCapacity = "V6"};
                default:
                    throw new Exception();
            }
        }
    }

Наконец, вызовы из внешнего проекта

            var nissanFactory = new NissanFactory();
            var sportsCar = nissanFactory.CreateCar(CarType.SportsCar);
            var pickUpTruck = nissanFactory.CreateCar(CarType.PickupTruck);

Но, как и в другом комментарии, Builder тоже стоит проверить.

...