我对实现此问题的最佳方法有疑问。我将描述我目前的实施情况,以及我如何将自己描绘成一个角落:
我有一个名为Package的抽象类:
public abstract class Package {
protected String description;
protected String packagingCode;
protected Dimension dimensions;
protected Weight weight;
protected Package() {
this.description = null;
this.packagingCode = null;
this.dimensions = null;
this.weight = null;
}
protected Package(String description, String packagingCode, Dimension dimensions, Weight weight) throws ShippingException {
this.description = description;
this.packagingCode = packagingCode;
this.dimensions = dimensions;
this.weight = weight;
String exceptionMessage = "";
if(!meetsWeightRequirements()) {
exceptionMessage = "This package's weight exceeds limits. ";
}
if(!meetsDimensionalRequirements()) {
exceptionMessage += "This package's dimensions exceed limits.";
}
if(!StringUtils.isEmpty(exceptionMessage)) {
throw new ShippingException(exceptionMessage);
}
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPackagingCode() {
return packagingCode;
}
public void setPackagingCode(String packagingCode) {
this.packagingCode = packagingCode;
}
public Dimension getPackageDimensions() {
return dimensions;
}
public void setPackageDimensions(Dimension dimensions) throws ShippingException {
this.dimensions = dimensions;
if(!meetsDimensionalRequirements()) {
this.dimensions = null;
throw new ShippingException("This package's dimensions exceed limits.");
}
}
public Weight getPackageWeight() {
return weight;
}
public void setPackageWeight(Weight weight) throws ShippingException {
this.weight = weight;
if(!meetsWeightRequirements()) {
this.weight = null;
throw new ShippingException("This package's weight exceeds limits.");
}
}
public abstract boolean meetsWeightRequirements();
public abstract boolean meetsDimensionalRequirements();
}
然后我有类扩展这个抽象类的类:
public class WeightBasedPackage extends Package {
public boolean meetsWeightRequirements() {
Weight weight = this.getPackageWeight();
boolean meetsRequirements = false;
if(weight != null) {
meetsRequirements = (weight.getWeight() > 0);
}
return meetsRequirements;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
我有另一个对象(ShipRequest
)维护一个包列表(List<Package>
)。我还有一个服务(例如WeightBasedPackageShipService
),它使用这个对象并可以访问这个包列表。这种实现工作正常,因为服务并不真正关心它是什么类型的包。包之间的唯一区别是它们实现抽象方法的方式。
现在问题就出现了。我创建了一个新类:
public class OrderQuantityPackage extends Package {
int quantity;
public OrderQuantityPackage() {
super();
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public int getQuantity() {
return this.quantity;
}
public boolean meetsWeightRequirements() {
return true;
}
public boolean meetsDimensionalRequirements() {
return true;
}
}
其中包含quantity
字段。我需要在服务中访问此字段(OrderQuantityPackageShipService
)。但是,由于它是Package
类型,我必须施放它(它看起来有点像kludgey)。
我的问题是,我如何以更好的方式实现这一点(所以我不需要强制转换)并确保类型安全(所以如果你使用OrderQuantityPackageShipService
,那么包必须是输入OrderQuantityPackage
)。我想过使用Generics,但是对于我想要做的事情来说似乎有点尴尬(ShipRequest
有一堆其他属性,根据包的类型对它进行泛化似乎很奇怪。)
感谢。
答案 0 :(得分:1)
public abstract class Package {
protected String description; // These shouldn't be private fields instead of protected?
protected String packagingCode; // Nah, I don't think so, otherwise how could I store a value into the Quantity field? =P
protected Dimension dimensions;
protected Weight weight;
protected int quantity;
// Constructors, getters and setters...
public virtual int getQuantity {
throw new NotImplementedException();
}
public virtual int setQuantity(int quantity) {
throw new NotImplementedException();
}
}
public final class OrderQuantityPackage extends Package {
public override int getQuantity {
return super.quantity;
}
public override void setQuantity(int quantity) {
super.quantity = quantity;
}
}
我不完全确定语法,也没有关于NotImplementedException,但我希望你明白这个想法。因此,任何需要或需要数量的Package派生类都可以通过覆盖Quantity属性的getter和setter来实现。
不应该抛出任何异常,因为不需要数量,不应该调用它,因此不应抛出任何异常。此外,它证明了您的模型仅在时机成熟时才能满足要求。
除此之外,OrderQuantityShipService不应要求OrderQuantityPackage中的Weight属性,并且如Vivin所写,无论如何都可以访问权重。
否则,您服务中的简单演员应该这样做。使用铸造并不是一种肮脏的方式。例如,必须将事件处理程序中的sender对象强制转换为他希望检查名称,状态或其他属性值的正确控件类型!最普通的课程然后被传递给活动,一个人必须投...然后,这不是我说选择这种方式的人,这些是软件工程师!...
编辑 Vivin,在JAVA中如何从数据类型转换为另一个,是否与C / C ++ / C#中一样?
CastedType variable = (CastedType)TypeCast;
答案 1 :(得分:0)
也许你应该创建一个抽象服务并扩展它以便处理不同类型的包。您可以将处理方法设计为抽象,并让各种服务知道如何处理相应的包。如果您不想混合使用各种类型的包,那么这可能会有效。
答案 2 :(得分:0)
简答:依赖性倒置
您有一个OrderQuantityPackageShipService类,需要来自其处理的对象的某些功能。因此,OrderQuantityPackageShipService应该是指定这些要求的那个。通常,这是通过接口完成的。如果它非常特定于服务,请创建嵌套的接口。即:
class OrderQuantityPackageShipService {
//...
interface QuantityPackage {
int getQuantity();
// ...
}
}
如果其他服务可以以一致的方式使用 ,请在OrderQuantityPackageShipService类之外定义它。
然后让某些包实现该接口......
答案 3 :(得分:0)
我能想到的一件事是你为什么需要访问班级quantity
中的OrderQuantityPackageShipService
属性?在我看来,你有一个getter和setter用于类Package
的每个属性。这些吸气剂和制定者真的需要吗?拥有所有这些属性的getter / setter并不适合封装。
您是否可以考虑在Package
类中提供更高级别的公共方法并且不公开内部属性?这不会有帮助吗?