商店设计 - 多种产品 类

Design for a shop - multiple product classes

我在阅读有关 Spring 的文章时遇到了一个示例,该示例由具有 nameprice 字段的抽象产品 class 组成。

接下来,有一个 Battery class 扩展了 Product class 并添加了一个 rechargable 字段。然后,CDDrive class(也)扩展了 Product 但添加了 capacity 字段。

在现实世界中,当我们经常拥有具有许多不同属性的产品时,如何为具有任意属性和字段的任意产品建模? 每个产品都有 class 有意义吗?

那么,你们能否提出实现此目标的模式?

谢谢, 乌尼

Does having a class for each product make sense?

对我来说,为单独的产品设置单独的 class 绝对有意义。 这使您的代码更加松散耦合。将来如果您想更改特定产品的实现,更改代码不会弄乱其他产品的实现,前提是您有一个单独的 class。您可以将通用方法和属性放入抽象 class.

a pattern for achieving this?

您可能想看看 Factory & template pattern

您可以创建一个接口 Product,所有 classes 都将实现该接口并定义它们自己的实现。

仅当您想为您的方法提供默认行为时才使用抽象class。例如,看看 template pattern here.

创建了一个抽象 class 游戏,它定义了 play 方法。 initializestartPlay 等可以在子 class 中有各自的定义,但 play 方法将始终 运行 其他方法。

public abstract class Game {
   abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();

   //template method
   public final void play(){

      //initialize the game
      initialize();

      //start game
      startPlay();

      //end game
      endPlay();
   }
}

如果您不打算提供任何默认行为,而只是在接口 Product 中声明属性和方法,让 classes 实现它。

interface Product{
String NAME="defaultName";
Integer PRICE=5;
initialCost(); // example of a generic method
}

//Note that name & price if you declare those in interface will be treated as constants.

class Battery implements Product{
 Boolean rechargable =false; 
 public void initialCost(){
 //method definition
}
}

class CdDrive implements Product{
 Integer capacity = xxxx;
 public void initialCost(){
 //CdDrive method definition
}
}

您可以将对象创建为

Product product = new Battery();
Product nextProduct = new CdDrive();

这会使您的代码松耦合。也称为接口编程。

好问题。我们之前遇到过类似的情况,我们的 GUI 组件共享许多抽象父级,但每个页面都有自己的一组标签,其他标签不共享。对峙开始了​​。我们发现继续创建子 class 是愚蠢的,因为它们具有相互不相交的属性。为我们做的是地图。首先,拥有一个 subclass 就是拥有一个或多个作为第一个 class 对象的区别属性。可充电电池和 CD 驱动器的容量。然后对于在构建时无法想到的属性,或者只是在次要命名约定上有所不同,请使用地图。我用下面的例子来演示。

产品:

public abstract class Product {
 String name;
 Double price;
 Map<String, Object> propMap;

 public Product(String name, Double price) {
    this.name = name;
    this.price = price;
    propMap = new HashMap<>();
 }

 public void add2propMap(String key, Object value) {
    propMap.put(key, value);
 }

 public String toString() {
    return "Product [name=" + name + ", price=" + price + ", propMap=" + propMap + "]";
 }
}

光驱:

public class CdDrive extends Product {

String capacity;

public CdDrive(String name, Double price, String capacity) {
    super(name, price);
    this.capacity = capacity;
}

}

电池:

public class Battery extends Product {

Boolean rechargable;

public Battery(String name, Double price, Boolean rechargable) {
    super(name, price);
    this.rechargable = rechargable;
}

}

然后一个客户:

public class Client {

public static void main(String[] args) {
    List<Product> productList = new ArrayList<>();

    Battery energizer = new Battery("Energizer", 12d, true);
    energizer.add2propMap("numInPackage", new Integer(8));
    energizer.add2propMap("make", "US");
    productList.add(energizer);

    CdDrive superDrive = new CdDrive("Apple Drive", 200d, "200 GB");
    superDrive.add2propMap("type", "External");
    superDrive.add2propMap("expandable", false);
    productList.add(superDrive);

    productList.forEach(p -> System.out.println(p));
}

}

当 运行:

Product [name=Energizer, price=12.0, propMap={numInPackage=8, make=US}]
Product [name=Apple Drive, price=200.0, propMap={expandable=false, type=External}]

此设置使体系结构可扩展、可维护和可修改。地图键始终报告其中的内容,以防有疑问。添加容易,修改也容易。

Does having a class for each product make sense?

在现实生活中,它很少有意义。他们只是编造了一些例子,让你感受一下。

试想一下,您的网上商店销售 CD 播放器,现在您想在您的产品列表中添加一些 MD 播放器,并且您需要更改代码并因此重新部署应用程序。废话吧?

除非您对某些特定类型的产品具有大量特定功能,否则为此类产品提供专用 class 将很有意义。 (例如 Product、PhysicallyDeliverableProduct 之类的东西。不过还有更好的设计方法)

在现实生活中,解决问题的方法主要是通过设计产品来保留一些任意属性(例如,保留 Map<String,Object>,因此您可以将 ["rechargeable", true] 用于您在网站上添加的电池。

设计模式?我认为您正在寻找的东西离使用模式还很远。就我个人而言,我会建议您看一下 Martin Fowler 的书 "Analysis Pattern"。你可能无法直接使用其中的设计,但它会让你感受到现实生活中的设计是什么样的