我在Java(7)应用程序中有以下设计:
有一种方法可以传递某些类型和对象的集合,我将其称为"谓词",用于过滤给定的集合.
Predicate是一个名为test的方法的接口 - 它接受一个对象并返回一个布尔值.
在这种情况下:
现在我想在C#(4.0)应用程序中有类似的设计.我可以看到两种方式 - 通过模仿Java设计,或通过将Predicate更改为委托:
我可以尝试模仿Java设计,但是:
我可以尝试使用委托来实现类似的设计.我的过滤方法将采用对象和谓词委托的集合.在这种情况下:
我的问题是 - 您认为在Java中实现相同(或尽可能相似)设计的最佳方式是什么,这将被视为正确,干净的C# - 这样做的方法?
我在Java编程方面有几年的经验,但在C#中不到一年的经验,所以我理解我可能看到的一些问题在C#世界中根本不存在或根本不被视为问题.
编辑:这是最简单的(我认为......)我的Java代码如何工作的可能示例:
我的"域名"对象:
public class Person {
private final String firstName;
private final String secondName;
public Person(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
public String getFirstName() {
return firstName;
}
public String getSecondName() {
return secondName;
}
}
Run Code Online (Sandbox Code Playgroud)
过滤类:
public class Filter {
public Collection<Person> filter(Collection<Person> collection, Predicate predicate) {
Collection<Person> result = new LinkedList<Person>();
for(Person person: collection) {
if(predicate.test(person)) {
result.add(person);
}
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
谓词界面:
public interface Predicate {
boolean test(Person person);
}
Run Code Online (Sandbox Code Playgroud)
两个简单的预定义实现
public class FirstNameStartsWithPredicate implements Predicate {
private final String startsWith;
public FirstNameStartsWithPredicate(String startsWith) {
this.startsWith = startsWith;
}
public boolean test(Person person) {
return person.getFirstName().startsWith(startsWith);
}
}
public class LastNameEndsWithPredicate implements Predicate {
private final String endsWith;
public LastNameEndsWithPredicate(String endsWith) {
this.endsWith = endsWith;
}
public boolean test(Person person) {
return person.getSecondName().endsWith(endsWith);
}
}
Run Code Online (Sandbox Code Playgroud)
实用类:
public final class PredicateUtils {
public static Predicate and(final Predicate first, final Predicate second) {
return new Predicate() {
public boolean test(Person person) {
return first.test(person) && second.test(person);
}
};
}
public static Predicate or(final Predicate first, final Predicate second) {
return new Predicate() {
public boolean test(Person person) {
return first.test(person) || second.test(person);
}
};
}
public static Predicate allwaysTrue() {
return new Predicate() {
public boolean test(Person person) {
return true;
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
最后,使用示例:
Collection<Person> persons = Arrays.asList(
new Person("John", "Done"),
new Person("Jane", "Done"),
new Person("Adam", "Smith")
);
Filter filter = new Filter();
// Predefined predicates
filter.filter(persons, new FirstNameStartsWithPredicate("J"));
filter.filter(persons, new LastNameEndsWithPredicate("e"));
// anonymous implementation
filter.filter(persons, new Predicate() {
public boolean test(Person person) {
return person.getFirstName().equals("Adam") && person.getSecondName().equals("Smith");
}
});
// utility class
filter.filter(persons, PredicateUtils.allwaysTrue());
filter.filter(persons, PredicateUtils.and(new FirstNameStartsWithPredicate("J"), new LastNameEndsWithPredicate("e")));
filter.filter(persons, PredicateUtils.or(new FirstNameStartsWithPredicate("J"), new FirstNameStartsWithPredicate("A")));
Run Code Online (Sandbox Code Playgroud)
这在C#中是完全可行的.假设我们有一些用户和过滤器来过滤它们,一些过滤器是内置的,一些是由用户实现的.在这里,我们应该使用Java之类的接口而不是委托.
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
public interface IPredicate<T>
{
bool IsValid(T entity);
}
public class UserPredicate : IPredicate<User>
{
/* built-in predicates */
public static UserPredicate Adult = new UserPredicate(u => u.Age >= 18);
public static UserPredicate NoAddress = new UserPredicate(u => string.IsNullOrEmpty(u.Address));
public Func<User, bool> Predicate { get; private set; }
public UserPredicate(Func<User, bool> predicate)
{
this.Predicate = predicate;
}
bool IPredicate<User>.IsValid(User entity)
{
return this.Predicate(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
用户可以轻松添加这样的新谓词:
//user's code
var custom = new UserPredicate(MyCustomUserFilter);
bool MyCustomUserFilter(User u)
{
//user's filter logic
}
Run Code Online (Sandbox Code Playgroud)
它与Java不同,因为在C#中,匿名类型无法实现接口.
而且将谓词"组合"成一个新的很容易.
var AdultWithNoAddress = new UserPredicate(u => UserPredicate.Adult.Predicate(u)
&& UserPredicate.NoAddress.Predicate(u));
Run Code Online (Sandbox Code Playgroud)
编辑为了使谓词组合更清晰,您可以将组合逻辑放入谓词本身.
public interface IPredicate<T>
{
bool IsValid(T entity);
IPredicate<T> And(IPredicate<T> another);
IPredicate<T> Or(IPredicate<T> another);
}
public class UserPredicate : IPredicate<User>
{
public static UserPredicate Adult = new UserPredicate(u => u.Age >= 18);
public static UserPredicate NoAddress = new UserPredicate(u => string.IsNullOrEmpty(u.Address));
private Func<User, bool> _predicate;
public UserPredicate(Func<User, bool> predicate)
{
_predicate = predicate;
}
public bool IsValid(User entity)
{
return _predicate(entity);
}
public IPredicate<User> And(IPredicate<User> another)
{
return new UserPredicate(u => this.IsValid(u) && another.IsValid(u));
}
public IPredicate<User> Or(IPredicate<User> another)
{
return new UserPredicate(u => this.IsValid(u) || another.IsValid(u));
}
}
//usage
var AdultWithNoAddress = UserPredicate.Adult.And(UserPredicate.NoAddress);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
182 次 |
| 最近记录: |