我认为以下内容可能非常适合策略模式,但我不确定这是否正确,如果是,那么如何正确实施。
我有一个接受Category和Sort的方法。目前分类和排序是枚举,所以像这样:
public enum Category{
Hot,
New
}
public enum Sort{
New,
Rising,
ThisWeek
}
public String getUrl(Category category, Sort sort){
validateCategorySortCombo(category, sort);
}
注意validateCategorySortCombo(Category,Sort)。首先,我必须验证组合 类别+排序有些是无效的。例如:
if(Category == "Hot" && Sort == "Rising"){
ThrowInvalidCategorySortCombo("Can't use hot category with rising sort")
}
将进行多项检查以确保组合有效。这似乎是一个代码气味,因为随着其他类别和类别的引入,我将不得不打开这个类并修改它打破了开放/封闭原则。
当我必须检查Category和Sort以构建我将传回的Url时,会出现第二个代码气味。目前我正在使用一系列switch语句:
String url;
switch(category){
case Hot:
url += "www.site.com/hot/";
case New:
url += "www.site.com/new/";
}
switch(sort){
case New:
url += "?sort=rising";
case ThisYear:
url += "?sort=thisyear";
}
同样,随着新类别和排序的引入,我将不得不打开这个类并更新switch语句。
几个问题:
答案 0 :(得分:3)
首先,我建议您在编写一些代码之前,先想到多种设计模式。允许您的代码告诉您哪种模式最有效。如果你事先选择一个,你最终可能会试图“强迫”你的代码使用一个可能不是最佳选择的模式。
话虽如此,在您的情况下可能最终有用的几种模式将是策略和Chain of Responsibility。
继续......
我认为您需要退后一步,根据您对系统随时间变化的预期,提出您的设计目标。例如,听起来你肯定期望添加新的类别和排序。基于此,您的设计可能有两个目标:
从这些目标出发,提出一种通用的方法。例如,我的想法是......
现在你可以开始考虑更多关于实现的问题(你有很多选择)。例如,您可以扩展枚举,以便每个值都已知道其url组件,如下所示:
public enum Sort{
New("?sort=new"),
Rising("?sort=rising"),
ThisWeek("?sort=thisweek");
private String urlComponent;
public Sort(String urlComponent) {this.urlComponent = urlComponent;)
public getUrlComponent() {return this.urlComponent;}
}
走这条路线,你总是可以调用mySort.getUrlComponent()
,这在添加/删除Sort枚举值时不需要改变。这将特别解决您的第二个问题。
我不能给你最好的实现或一组设计模式,因为我不知道你对你正在构建的系统所做的一切,但我希望我的想法会有所帮助。
答案 1 :(得分:2)
import java.util.*;
enum Category {
Hot(EnumSet.of(Sort.Rising)),New(EnumSet.of(Sort.ThisWeek,Sort.ThisYear));
Category(EnumSet<Sort> legal) {
this.legal.addAll(legal);
}
boolean isLegal(Sort sort) {
return legal.contains(sort);
}
private final EnumSet<Sort> legal=EnumSet.noneOf(Sort.class);
}
enum Sort {
New,Rising,ThisWeek,ThisYear;
}
public class So9706550 {
static boolean isValid(Category category,Sort sort) {
return category.isLegal(sort);
}
public static void main(String[] args) {
System.out.println(isValid(Category.Hot,Sort.Rising));
System.out.println(isValid(Category.Hot,Sort.ThisWeek));
}
}
答案 2 :(得分:1)
只需将排序顺序的验证移至类别枚举即可。所以它显示为category.isValidSort(sort);
答案 3 :(得分:0)
第一个问题 -
您可以定义一个特别是hashmap
的验证器,其密钥将是Category和Sort的组合。
您可以使用有效组合预先填充此地图[可以考虑硬编码/配置文件驱动/定期刷新等]。
在validateCategorySortCombo
中,您可以检查散列图是否实际包含密钥?如果是的话,那就好了。
-
Map<Compositekey<Sort,Category>,Boolean> validOptions = new hashMap..
void validateCategorySortCombo(category, sort){
if(validOptions.containskey(category,sort)){
//good to go
}
}
答案 4 :(得分:0)
我注意到您不仅验证了输入,还根据它们编写了一个URL字符串。 虽然看起来像Abstract Factory的经典案例,但它可能有点过度使用。 您可能拥有类别的抽象族和具体实现SortedCategories。 其他好处是您可以在HotRaisedFactory中明确地将异常引发为该类别和Sort的不可接受的组合。