我正在阅读有关Spring的内容,并遇到了一个包含name
和price
字段的抽象产品类的示例。
接下来,有一个Battery
类扩展了Product
类并添加了rechargable
字段。然后,CDDrive
类(也)扩展Product
但添加了capacity
字段。
在现实世界中,当我们经常拥有具有许多不同属性的产品时,如何使用任意属性和字段对任意产品进行建模? 每个产品的课程都有意义吗?
那么,你们可以提出一个实现这个目标的模式吗?
谢谢, Ouney
答案 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。您可能无法直接使用其中的设计,但它可以让您感受到真实设计的外观