Tôi đang triển khai một công cụ quy tắc trong Java. Công cụ quy tắc của tôi xác định trước danh sách các quy tắc và quy tắc độc lập. Một quy tắc ở đây chỉ đơn giản là một phần của logic. Và một bộ quy tắc kết hợp các quy tắc đơn giản này thành một tập hợp có thứ tự.Mẫu/kiểu thiết kế hiệu quả cho việc thiết kế một công cụ quy tắc trong Java là gì?
Tôi là một nhà phát triển java phong nha nhưng không phải là một Guru. Đồng nghiệp của tôi đề nghị tôi hai thiết kế cho mục đích này. Tôi không hài lòng với cả hai thiết kế, do đó câu hỏi này.
Ví dụ về một quy tắc trong dự án của tôi: Giả sử đầu vào là địa điểm tại Mỹ cho ví dụ, Santa Barbara, CA, USA hoặc OH, mà Mỹ thường là trong một số định dạng được xác định rõ với các thành phố, tiểu bang và đất nước lĩnh vực. Sau đó, tôi có thể có một số quy tắc như sau:
Quy tắc 1: Thành phố không phải là null
Quy tắc 2: Nhà nước không phải là null
Quy tắc 3: Country là Mỹ hoặc Mỹ
Quy tắc 4: chiều dài Nhà nước bằng 2
Ví dụ về một ruleset trong dự án của tôi:
RULESET: Vị trí hợp lệ Quy tắc này là tập hợp theo thứ tự các quy tắc được xác định ở trên.
Hai mẫu thiết kế tôi đã thực hiện như sau:
Thiết kế 1: Sử dụng Enum với các lớp Anonymous Nội
Rule.java
public interface Rule {
public Object apply(Object object);
}
NlpRule.java
public enum NlpRule {
CITY_NOT_NULL(new Rule() {
@Override
public Object apply(Object object) {
String location = (String) object;
String city = location.split(",")[0];
if (city != null) {
return true;
}
return false;
}
}),
STATE_NOT_NULL(new Rule() {
@Override
public Object apply(Object object) {
String location = (String) object;
String state = location.split(",")[1];
if (state != null) {
return true;
}
return false;
}
}),
COUNTRY_US(new Rule() {
@Override
public Object apply(Object object) {
String location = (String) object;
String country = location.split(",")[2];
if (country.equals("US") || country.equals("USA")) {
return true;
}
return false;
}
}),
STATE_ABBREVIATED(new Rule() {
@Override
public Object apply(Object object) {
String location = (String) object;
String state = location.split(",")[1];
if (state.length() == 2) {
return true;
}
return false;
}
});
private Rule rule;
NlpRule(Rule rule) {
this.rule = rule;
}
public Object apply(Object object) {
return rule.apply(object);
}
}
RuleSet.java
public class RuleSet {
private List<NlpRule> rules;
public RuleSet() {
rules = new ArrayList<NlpRule>();
}
public RuleSet(List<NlpRule> rules) {
this.rules = rules;
}
public void add(NlpRule rule) {
rules.add(rule);
}
public boolean apply(Object object) throws Exception {
boolean state = false;
for (NlpRule rule : rules) {
state = (boolean) rule.apply(object);
}
return state;
}
}
RuleSets.java
public class RuleSets {
private RuleSets() {
}
public static RuleSet isValidLocation() {
RuleSet ruleSet = new RuleSet();
ruleSet.add(NlpRule.CITY_NOT_NULL);
ruleSet.add(NlpRule.STATE_NOT_NULL);
ruleSet.add(NlpRule.COUNTRY_US);
ruleSet.add(NlpRule.STATE_ABBREVIATED);
return ruleSet;
}
}
Main.java
public class Main {
public static void main(String... args) {
String location = "Santa Barbara,CA,USA";
RuleSet ruleSet = RuleSets.isValidLocation();
try {
boolean isValid = (boolean) ruleSet.apply(location);
System.out.println(isValid);
} catch (Exception e) {
e.getMessage();
}
}
}
Thiết kế 2: Sử dụng Abstract class
NlpRule.java
public abstract class NlpRule {
public abstract Object apply(Object object);
public final static NlpRule CITY_NOT_NULL = new NlpRule() {
public Object apply(Object object) {
String location = (String) object;
String city = location.split(",")[0];
if (city != null) {
return true;
}
return false;
}
};
public final static NlpRule STATE_NOT_NULL = new NlpRule() {
public Object apply(Object object) {
String location = (String) object;
String city = location.split(",")[0];
if (city != null) {
return true;
}
return false;
}
};
public final static NlpRule COUNTRY_US = new NlpRule() {
public Object apply(Object object) {
String location = (String) object;
String country = location.split(",")[2];
if (country.equals("US") || country.equals("USA")) {
return true;
}
return false;
}
};
public final static NlpRule STATE_ABBREVIATED = new NlpRule() {
public Object apply(Object object) {
String location = (String) object;
String state = location.split(",")[1];
if (state.length() == 2) {
return true;
}
return false;
}
};
}
ruleset.java
public class RuleSet {
private List<NlpRule> rules;
public RuleSet() {
rules = new ArrayList<NlpRule>();
}
public RuleSet(List<NlpRule> rules) {
this.rules = rules;
}
public void add(NlpRule rule) {
rules.add(rule);
}
public boolean apply(Object object) throws Exception {
boolean state = false;
for (NlpRule rule : rules) {
state = (boolean) rule.apply(object);
}
return state;
}
}
RuleSets.java
import com.hgdata.design.one.NlpRule;
import com.hgdata.design.one.RuleSet;
public class RuleSets {
private RuleSets() {
}
public static RuleSet isValidLocation() {
RuleSet ruleSet = new RuleSet();
ruleSet.add(NlpRule.CITY_NOT_NULL);
ruleSet.add(NlpRule.STATE_NOT_NULL);
ruleSet.add(NlpRule.COUNTRY_US);
ruleSet.add(NlpRule.STATE_ABBREVIATED);
return ruleSet;
}
}
Main.java
public class Main {
public static void main(String... args) {
String location = "Santa Barbara,CA,USA";
RuleSet ruleSet = RuleSets.isValidLocation();
try {
boolean isValid = (boolean) ruleSet.apply(location);
System.out.println(isValid);
} catch (Exception e) {
e.getMessage();
}
}
}
Better Thiết kế tiếp cận/Pattern? Như bạn có thể thấy, thiết kế 2 loại bỏ giao diện và enum. Thay vào đó, nó sử dụng một lớp trừu tượng. Tôi vẫn tự hỏi nếu có một mẫu thiết kế tốt hơn/cách tiếp cận để thực hiện như vậy.
õ sử dụng khối initializer:
Bây giờ trong trường hợp của cả hai thiết kế trên. Nói, nếu tôi cần phải nhanh chóng một lớp bên ngoài để sử dụng nó bên trong logic áp dụng của tôi, sau đó tôi buộc phải sử dụng các khối khởi tạo mà tôi không hoàn toàn nhận thức được liệu đó có phải là một thực hành tốt hay không. Xem ví dụ cho một kịch bản như vậy dưới đây:
Thiết kế 1:
...
STATE_ABBREVIATED(new Rule() {
private CustomParser parser;
{
parser = new CustomParser();
}
@Override
public Object apply(Object object) {
String location = (String) object;
location = parser.parse(location);
String state = location.split(",")[1];
if (state.length() == 2) {
return true;
}
return false;
}
});
...
Thiết kế 2:
...
public final static NlpRule STATE_ABBREVIATED = new NlpRule() {
private CustomParser parser;
{
parser = new CustomParser();
}
public Object apply(Object object) {
String location = (String) object;
location = parser.parse(location);
String state = location.split(",")[1];
if (state.length() == 2) {
return true;
}
return false;
}
};
...
chuyên gia Java xin đúc một số ánh sáng! Ngoài ra xin vui lòng xác định nếu bạn tìm thấy bất kỳ sai sót trong hai thiết kế trên. Tôi cần biết những ưu và khuyết điểm liên quan đến từng thiết kế để giúp tôi đưa ra quyết định đúng đắn. Tôi đang xem xét lambdas, predicates và một số mẫu khác theo gợi ý của một số người dùng trong các ý kiến.
Không gây phiền toái, nhưng tại sao đây không phải là vấn đề về regex? Regex là một "ruleset" khá phát triển và được thử nghiệm chống lại các chuỗi. Thậm chí nếu bạn muốn chia các regex ra thành các đối tượng riêng của chúng, bạn có thể 1) sử dụng các đối tượng đó trong một mảng, 2) yêu cầu mỗi đối tượng cho regex 3) biên dịch thành regex lớn hơn (và đó có thể là ruleset của bạn) – LLFourn
@LLFourm Các quy tắc tôi đã trình bày ở trên thực sự đơn giản. Tôi có hơn 100 quy tắc mà tôi sẽ cần phải thực hiện. Và hầu hết các quy tắc có logic phức tạp và phụ thuộc vào các lớp khác. Đây không thực sự là một vấn đề về regex. – Shankar
Sử dụng JavaCompilerAPI: http://docs.oracle.com/javase/7/docs/api/javax/tools/JavaCompiler.html.Không thể nói nhiều hơn, tôi không biết nhiều về java. – Fendy