Загрузка повторных изображений + текстовые поля в ASP.NET MVC

Декоратор - это класс, который расширяет функциональность другого класса. Декоратор обычно реализует тот же интерфейс, так что декорированный объект можно использовать вместо базового. Хорошим примером является компрессор и / или шифратор, применяемый к файлу или, в более общем смысле, к реализации потока данных, как показано в ответе @ nits.kk . [1116 ]

В случае пиццы мы должны определить, какое поведение нам нужно:

public interface Pizza {
    public String getIngredients();  // comma separated
    public double getTotalPrice();
}

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

public class PizzaIngredient {
    private double getPrice() {
        return 0.0;
    }
}

База пиццы сама по себе является самой простой пиццей, поэтому она должна реализовывать интерфейс Pizza. У него есть размер как его атрибут (и цена, конечно). Мы могли бы реализовать размер как отдельный класс, но я не считаю его разумным - он недостаточно универсален, чтобы быть полезным вне вселенной пиццы, и недостаточно сложен, чтобы заслужить свой собственный интерфейс.

public class PizzaBase extends PizzaIngredient implements Pizza {
    public PizzaBase(String size) {
        this.size = size;
    }

    public String getIngredients() {
        return size + " base";  // the only ingredient is this base
    }
    public double getTotalPrice() {
        return getPrice();      // the base-only pizza costs the base cost
    }
    private double getPrice() {
        if(size == "small")
            return 2.0;
        if(size == "medium")
            return 2.5;

        return 3.0;            // large and undefined
    }

    private final String size;
}

Теперь нам нужны начинки. Они будут добавлены поверх пиццы в качестве декораторов: пицца плюс топпинг - это тоже пицца, поэтому самый верхний топинг будет представлять всю композицию. Список ингредиентов такой пиццы - это список ингредиентов основной пиццы, а также наименование ее самой верхней части. Аналогично общая цена.

public class PizzaTopping extends PizzaIngredient implements Pizza {
    public PizzaTopping(String name, Pizza pizza) {
        this.name = name;
        this.pizza = pizza;
    }

    public String getIngredients() {
        return pizza.getIngredients() + ", " + getName();
    }
    public double getTotalPrice() {
        return pizza.getTotalPrice() + getPrice();
    }
    public String getName() {
        return name;
    }

    private final String name;
    private final Pizza pizza;
}

Давайте определим некоторые конкретные начинки:

public class MozarellaTopping extends PizzaTopping {
    public MozarellaTopping(Pizza pizza) {
        super("mozarella", pizza);
    }

    private double getPrice() {
        return 0.5;
    }
}

public class MushroomTopping extends PizzaTopping {
    public MushroomTopping(Pizza pizza) {
        super("mushroom", pizza);
    }

    private double getPrice() {
        return 2.0;
    }
}

public class PepperoniTopping extends PizzaTopping {
    public PepperoniTopping(Pizza pizza) {
        super("pepperoni", pizza);
    }

    private double getPrice() {
        return 1.5;
    }
}

public class GreenOliveTopping extends PizzaTopping {
    public GreenOliveTopping(Pizza pizza) {
        super("green olive", pizza);
    }

    private double getPrice() {
        return 1.2;
    }
}

Хорошо, это много классов; но какой из них и когда нам понадобится?

Здесь фабрика присоединяется к команде. Фабрика - это класс для создания объектов некоторых классов. Он используется, чтобы скрыть детали создания за кулисами, особенно когда созданные объекты являются сложными или имеют разные конкретные классы. Когда результирующие объекты создаются как автономные объекты, фабричный класс может быть просто пространством имен со статическим методом в нем. OTOH, если объекты создаются в каком-то контексте, фабрика может быть объектом, связанным с контекстом (например, параметризованным) и использующим этот контекст в процессе создания.

Мы можем использовать фабрику для создания ингредиентов для пиццы по желанию, в соответствии с пользовательской информацией. Большинство ингредиентов - это начинки, которые нужно наносить поверх уже существующей пиццы, поэтому давайте передадим пиццу на фабрику, чтобы в результате получить украшенную пиццу. Особый случай - создание базы для пиццы, которая не наносится на другую пиццу; в этом случае параметр pizza игнорируется, поэтому мы можем передать null.

public class PizzaFactory {
    public static Pizza getPizza(Pizza pizza, String name)
    {
        if ( name.equals("small") || name.equals("medium") || name.equals("large") )
            return new PizzaBase(name);
        else if ( name.equals("mozarella") )
            return new MozarellaTopping(pizza);   // add topping to the pizza
        else if ( name.equals("mushroom") )
            return new MushroomTopping(pizza);
        else if ( name.equals("pepperoni") )
            return new PepperoniTopping(pizza);
        else if ( name.equals("green olive") )
            return new GreenOliveTopping(pizza);

        return null;
    }
}

Теперь мы готовы построить нашу пиццу.

class PizzaTest {
    public static void main(String[] args) {
        DecimalFormat priceFormat = new DecimalFormat("#.##");

        Pizza pizza;

        pizza = PizzaFactory.getPizza(null, "small");
        System.out.println("The small pizza is: " + pizza.getIngredients());
        System.out.println("It costs " + priceFormat.format(pizza.getTotalCost()));

        pizza = PizzaFactory.getPizza(null, "medium");
        pizza = PizzaFactory.getPizza(pizza, "mozarella");
        pizza = PizzaFactory.getPizza(pizza, "green olive");

        System.out.println("The medium pizza is: " + pizza.getIngredients());
        System.out.println("It costs " + priceFormat.format(pizza.getTotalCost()));

        String largePizzaOrder[] = { "large", "mozarella", "pepperoni",
                                     "mushroom", "mozarella", "green olive" };

        pizza = null;
        for (String cmd : largePizzaOrder)
            pizza = PizzaFactory.getPizza(pizza, cmd);

        System.out.println("The large pizza is: " + pizza.getIngredients());
        System.out.println("It costs " + priceFormat.format(pizza.getTotalCost()));
    }
}

Предупреждение: в приведенном выше коде есть некоторые подводные камни и ярлыки.

Наиболее важным является отсутствие проверки ввода: при поступлении неожиданной команды, фабрика вернет null, что вызовет сбой при будущем использовании getIngredients() или getTotalCost().

Другой - жесткое кодирование цен в конкретные классы. Фактическое решение должно было бы использовать некоторый прайс-лист и получать цены либо при создании ингредиента (и хранить выбранные цены в объектах ингредиента), либо при использовании, т. Е. В методе getCost() (который потребовал бы некоторого доступа к прайс-листу от ингредиенты пиццы).

5
задан Community 23 May 2017 в 12:26
поделиться

1 ответ

В Вашем контроллере можно получить доступ к загруженным файлам как:

    if(Request.Files.Count > 0 && Request.Files[0].ContentLength > 0) {
        HttpPostedFileBase postFile = Request.Files.Get(0);
        string filename = GenerateUniqueFileName(postFile.FileName);
        postFile.SaveAs(server.MapPath(FileDirectoryPath + filename));
    }

protected virtual string GenerateUniqueFileName(string filename) {

    // get the extension
    string ext = Path.GetExtension(filename);
    string newFileName = "";

    // generate filename, until it's a unique filename
    bool unique = false;

    do {
        Random r = new Random();
        newFileName = Path.GetFileNameWithoutExtension(filename) + "_" + r.Next().ToString() + ext;
        unique = !File.Exists(FileDirectoryPath + newFileName);
    } while(!unique);
    return newFileName;
}

Текстовые поля достигнут Вашего действия контроллера как обычно т.е. Запроса. Форма [...]. Обратите внимание, что необходимо будет также установить enctype на форме к "multipart/form-data". Это кажется на понимание достаточно о ASP.NET MVC, чтобы сделать остальных. Обратите внимание также, что можно объявить тег form в представлении aspx следующим образом, хотя можно использовать более традиционный подход, если Вам нравится.

<% using(Html.BeginForm<FooController>(c => c.Submit(), FormMethod.Post, new { enctype = "multipart/form-data", @id = formId, @class = "submitItem" })) { %> 

<% } %>
7
ответ дан 14 December 2019 в 04:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: