Builder или другой шаблон, чтобы всегда создавать экземпляр в допустимом состоянии - PullRequest
0 голосов
/ 28 октября 2009

У меня очень сложная настройка объектов, и каждый выбор по пути ограничивает или расширяет доступные опции. Я бы не хотел бросать исключения или создавать недопустимый экземпляр объекта. Итак, я хочу ограничить параметры (методы, доступные для вызова) при построении экземпляра на основе параметров ввода предыдущего метода. Например, если у меня есть некоторые правила, которые говорят, что если пользователь имеет тип «A», то разрешить его добавление в роли, в противном случае, если он имеет тип «B», запросить местоположение и если местоположение находится в определенном почтовом индексе ... идея

Возможно ли это с помощью анонимных методов, типов, чего угодно

тип пользователя A

UserBuilder builder = new UserBuilder
builer.Build().ForType("A").WithRoles(rolesList);

тип пользователя B

UserBuilder builder = new UserBuilder
builer.Build().ForType("B").WithLocations(locationList);

Обновление: Поэтому в основном мой вопрос таков: есть ли способ ограничить все остальные параметры публичного метода из API, кроме допустимых, основанных на состоянии объекта.

Ответы [ 2 ]

2 голосов
/ 28 октября 2009

Да, это было бы теоретически возможно. (Хотя анонимные методы / типы, скорее всего, не будут задействованы.)

Однако, использование будет немного кошмаром. К сожалению, если вы используете эти типы ограничений в использовании свободного интерфейса, вам нужно знать правила, чтобы понять, как «создать» тип.

Я бы предпочел создавать специализированные пользовательские подклассы для разных типов пользователей. Пусть конструкторы каждого подкласса требуют, чтобы параметры, необходимые для них, были правильно инициализированы, и предоставили необходимые методы и свойства.

Таким образом, вы просто делаете соответствующего пользователя:

UserA userA = new UserA(rolesList); // This requires roles to construct
UserB userB = new UserB(locationList); // This requires locations to construct
0 голосов
/ 28 октября 2009

Вы можете сделать что-то вроде приведенного ниже кода, который, очевидно, является просто концепцией. Проблема заключается в том, что вам нужно кодировать вызовы методов для каждого типа в цепочке, чтобы поддерживать свободный интерфейс.

class Program
{
    static void Main(string[] args)
    {
        var builder = new UserBuilder();
        builder.BuildTypeA().WithRoles("a,b");
        builder.BuildTypeB().WithLocations("c,d");
    }
}

public abstract class User {}
public class UserA : User {}
public class UserB : User {}

public class UserBuilder
{
    public UserABuilder BuildTypeA() { return new UserABuilder(); }
    public UserBBuilder BuildTypeB() { return new UserBBuilder(); }
}

public class UserABuilder
{
    public UserABuilder WithRoles(string roles)
    {
        // add roles
        return this;
    }
}

public class UserBBuilder
{
    public UserBBuilder WithLocations(string locations)
    {
        // add locations
        return this;
    }
}
...