为商店设计 - 多个产品类别

时间:2015-05-22 02:09:04

标签: java design-patterns

我正在阅读有关Spring的内容,并遇到了一个包含nameprice字段的抽象产品类的示例。

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

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

那么,你们可以提出一个实现这个目标的模式吗?

谢谢, Ouney

3 个答案:

答案 0 :(得分:3)

好问题。在我们拥有共享许多抽象父级的GUI组件之前,我们遇到了类似的情况,但每个页面都有自己的标签集,而这些标签并没有被其他人共享。对峙正在进行中。我们发现继续创建子类因为它们具有相互不相交的属性而感到愚蠢。它对我们来说是地图。首先,要使子类具有一个或多个作为第一类对象的区别属性。在您的情况下可充电电池和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 + "]";
 }
}

CdDrive:

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}]

此设置使架构可扩展,可维护和可修改。如果有疑问,地图键总是报告那里的内容。添加很容易,因此正在修改。

答案 1 :(得分:0)

  

每个产品的课程都有意义吗?

对我而言,为单独的产品设置单独的类是绝对有意义的。 这使得您的代码更加松散耦合。将来,如果您想要更改特定产品的实现,如果您有一个单独的类,更改代码不会搞砸其他产品的实现。通用方法&amp;你可以把它放在一个抽象类中。

  

实现这一目标的模式?

您可能需要查看Factory&amp; template pattern

您可以创建一个界面Product&amp;所有类都将实现该接口&amp;定义自己的实现。

仅当您要为方法提供默认行为时才使用抽象类。有关实例,请查看template pattern here

创建一个定义play方法的抽象类游戏。 initialize&amp; startPlay等可以在子类中有各自的定义,但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();
   }
}

如果您不打算提供任何默认行为,而只是声明属性&amp;界面中的方法Product&amp;让这些类实现它。

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();

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

答案 2 :(得分:0)

  

每个产品的课程都有意义吗?

在现实生活中,它很少有意义。他们只是举一些例子来让你感受到它。

想象一下,您的在线商店销售CD播放器,现在您想在产品列表中添加一些MD播放器,您需要更改代码并重新部署应用程序。无意义吧?

除非您对某些特定类型的产品具有特定功能,否则为此类产品设置专用类将是有意义的。 (例如Product,PhysicallyDeliverableProduct之类的东西。虽然有更好的方法来设计它)

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

设计模式?我认为你所寻找的东西还远远不需要使用模式。就个人而言,我建议你看看这本书&#34;分析模式&#34;作者:Martin Fowler。您可能无法直接使用其中的设计,但它可以让您感受到真实设计的外观