Программирование на интерфейс

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

У меня был класс и некоторый набор свойств. Через некоторое время мое требование изменилось и я вынужден был добавить два свойства с именем ItemAssociatedToProduct а также ItemAssociatedToOffers, Создание объекта с этими свойствами заставляет меня волноваться и решил разделить класс, имея Offer класс и Product класс, наследующий Item учебный класс. Я думал исключить конкретную реализацию моего объекта. Так что в моем классе пользовательского интерфейса я хочу создать такой объект,

Item myItem = new Product() // or Offer()

Так что я могу достичь абстракции. Но поскольку у класса Item нет дополнительных свойств, которые есть у производного класса, я не могу на него ссылаться. Я подумал, что должен использовать проверку "is" для определения типа и приведения типа к соответствующему объекту. Но снова его бьют вокруг куста. Разве это не способ решить мой сценарий, но в то же время придерживаться абстракции или этот принцип предназначен только для использования его для поведения (метод / функция), а не для данных (свойства)?

Адам Лисс -> теперь это правильно:)?

class Program 
{
    static void Main(string[] args)
    {
        Item myProduct = new Product();
        myProduct.ProductName = "CellPhone";
        myProduct.ProductPrice = "$300";
        myProduct.ItemType = myProduct.GetProductOrOffer();

        Item myOffer = new Offer();
        myOffer.ProductName = "CellPhoneCover";
        myOffer.ProductPrice = "$0";
        myOffer.ItemType = myOffer.GetProductOrOffer();
    }
}

interface Item
{
    String GetProductOrOffer();
    String ProductName
    {
        get;
        set;
    }

    String ProductPrice
    {
        get;
        set;
    }

    String ItemType
    {
        get;
        set;
    }

}

class Product : Item
{
    public String GetProductOrOffer()
    {
        return "Product";
    }

    public String ItemType
    {
        get;
        set;
    }

    public string ProductName
    {
        get;
        set;
    }

    public string ProductPrice
    {
        get;
        set;
    }
}

class Offer : Item
{
    public String GetProductOrOffer()
    {
        return "Offer";
    }

    public String ItemType
    {
        get;
        set;
    }

    public string ProductName
    {
        get;
        set;
    }

    public string ProductPrice
    {
        get;
        set;
    }
}

2 ответа

Решение

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

Это может быть легче понять на примере.

interface Item {
  getItemType();
  getName();
  getDescription();
  getPrice();
}

class Product implements Item {
  getItemType()        { return "Product"; }
  getName()            { /* implementation here */ }
  getDescription()     { /* implementation here */ }
  getPrice()           { /* implementation here */ }
  getManufacturer()    { /* implementation here */ }
  getWholesaleCost()   { /* implementation here */ }
}

class Offer implements Item {
  getItemType()        { return "Offer"; }
  getName()            { /* implementation here */ }
  getDescription()     { /* implementation here */ }
  getPrice()           { /* implementation here */ }
  getExpirationDate(); { /* implementation here */ }
  getFinePrint();      { /* implementation here */ }
}

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

Но любой может также написать общий метод, который заботится только о том, чтобы его аргумент Item, как это:

main() {

  Product myProduct = new Product();
  myProduct.name = "SuperExtraPolyWidget";
  myProduct.description = "The best widget you can buy!";
  myProduct.price = 1428.57;
  myProduct.manufacturer = "SuperExtra, Inc.";
  myProduct.wholesaleCost = 314.15;

  Offer myOffer = new Offer();
  myOffer.name = "WonderBargainDeal";
  myOffer.description = "The deal you've wondered about";
  myOffer.price = 0;
  myOffer.expirationDate = Date(yesterday);
  myOffer.finePrint = "Valid between 1:23 and 1:24 AM February 29.";

  List<Item> itemList = List.of(myProduct, myOffer);
  printCatalog(itemList);
}

printCatalog(List<Item> items) {
  for (Item item in items) {
    printf("%s: %s\n", item.getItemType(), item.getName());
    printf("------------------\n");
    printf("%s\n\n", item.getDescription());
  }
}

Это может распечатать каталог из списка Productс или Offers (или оба), потому что он использует только методы, которые определены в Item интерфейс.

Важно использовать наследование, только если оно имеет смысл и является подходящим способом моделирования объектов домена. Продукт и Предложение должны реализовывать Предмет только в том случае, если существует отношение "есть": Продукт - это Предмет, а Предложение - это Предмет.

Это тот случай? Не зная деталей вашего заявления, мы не знаем наверняка. Но я работал над некоторыми коммерческими приложениями, где Item представлял собой конкретную позицию заказа для общего типа Продукта, и в этих случаях Продукты вообще не были Элементами. Элемент может иметь атрибут Product, относящийся к конкретному типу Product, который представляет этот Item. Аналогично для предложений - если Предложение не является Предметом, это должен быть отдельный класс, и, возможно, Предметы будут иметь атрибут, который связывает его с Предложениями, используемыми для покупки этого Предмета.

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

В заключение, просто убедитесь, что ваше моделирование соответствует тому, что представляют эти объекты.

Другие вопросы по тегам