商店设计 - 多种产品 类
Design for a shop - multiple product classes
我在阅读有关 Spring 的文章时遇到了一个示例,该示例由具有 name
和 price
字段的抽象产品 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
方法。 initialize
和 startPlay
等可以在子 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"。你可能无法直接使用其中的设计,但它会让你感受到现实生活中的设计是什么样的
我在阅读有关 Spring 的文章时遇到了一个示例,该示例由具有 name
和 price
字段的抽象产品 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
方法。 initialize
和 startPlay
等可以在子 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"。你可能无法直接使用其中的设计,但它会让你感受到现实生活中的设计是什么样的