规格模式(Specification Pattern):它是组合模式的一种特殊应用。同时,每个规格书都是一个策略,它完成了一系列逻辑的封装。
抽象规格书ISpecification:
public interface ISpecification {
//候选者是否满足要求
public boolean isSatisfiedBy(Object candidate);
//and操作
public ISpecification and(ISpecification spec);
//or操作
public ISpecification or(ISpecification spec);
//not操作
public ISpecification not();
}
组合规格书CompositeSpecification:
public abstract class CompositeSpecification implements ISpecification {
//是否满足条件由实现类实现
public abstract boolean isSatisfiedBy(Object candidate);
//and操作
public ISpecification and(ISpecification spec) {
return new AndSpecification(this,spec);
}
//not操作
public ISpecification not() {
return new NotSpecification(this);
}
//or操作
public ISpecification or(ISpecification spec) {
return new OrSpecification(this,spec);
}
}
与规格书AndSpecification:
public class AndSpecification extends CompositeSpecification {
//传递两个规格书进行and操作
private ISpecification left;
private ISpecification right;
public AndSpecification(ISpecification _left,ISpecification _right){
this.left = _left;
this.right = _right;
}
//进行and运算
@Override
public boolean isSatisfiedBy(Object candidate) {
return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate);
}
}
或规格书OrSpecification:
public class OrSpecification extends CompositeSpecification {
//左右两个规格书
private ISpecification left;
private ISpecification right;
public OrSpecification(ISpecification _left,ISpecification _right){
this.left = _left;
this.right = _right;
}
//or运算
@Override
public boolean isSatisfiedBy(Object candidate) {
return left.isSatisfiedBy(candidate) || right.isSatisfiedBy(candidate);
}
}
非规格书NotSpecification:
public class NotSpecification extends CompositeSpecification {
//传递一个规格书
private ISpecification spec;
public NotSpecification(ISpecification _spec){
this.spec = _spec;
}
//not操作
@Override
public boolean isSatisfiedBy(Object candidate) {
return !spec.isSatisfiedBy(candidate);
}
}
业务规格书BizSpecification:
public class BizSpecification extends CompositeSpecification {
//基准对象
private Object obj;
public BizSpecification(Object _obj){
this.obj = _obj;
}
@Override
public boolean isSatisfiedBy(Object candidate) {
//根据基准对象和候选对象,进行业务判断,返回boolean
return false;
}
}
public class Client {
public static void main(String[] args) {
//待分析的对象
ArrayList
查找出姓名中包含“国庆”两个字的用户,这在关系型数据库中很容易实现,但是在对象群中怎么实现这样的查询呢?
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//用户信息打印
@Override
public String toString() {
return "用户名:" + name + "\t年龄:" + age;
}
}
import java.util.ArrayList;
import com.sfq.action.User;
public interface IUserProvider {
//根据条件查找用户
public ArrayList findUser(IUserSpecification userSpec);
}
import java.util.ArrayList;
import com.sfq.impl.IUserProvider;
import com.sfq.impl.IUserSpecification;
public class UserProvider implements IUserProvider {
//用户列表
private ArrayList userList;
public UserProvider(ArrayList userList) {
this.userList = userList;
}
@Override
public ArrayList findUser(IUserSpecification userSpec) {
ArrayList result = new ArrayList();
for(User u:userList) {
if (userSpec.isSatisfiedBy(u)) {
result.add(u);
}
}
return result;
}
}
import com.sfq.action.User;
public interface IUserSpecification {
//候选者是否满足要求
public boolean isSatisfiedBy(User user);
public IUserSpecification and(IUserSpecification spec);//与
public IUserSpecification or(IUserSpecification spec);//或
public IUserSpecification not();//非
}
import com.sfq.action.AndSpecification;
import com.sfq.action.NotSpecification;
import com.sfq.action.OrSpecification;
import com.sfq.action.User;
public abstract class CompositeSpecification implements IUserSpecification {
public abstract boolean isSatisfiedBy(User user);
@Override
public IUserSpecification and(IUserSpecification spec) {
return new AndSpecification(this,spec);
}
@Override
public IUserSpecification or(IUserSpecification spec) {
return new OrSpecification(this,spec);
}
@Override
public IUserSpecification not() {
return new NotSpecification(this);
}
}
//and
import com.sfq.impl.CompositeSpecification;
import com.sfq.impl.IUserSpecification;
public class AndSpecification extends CompositeSpecification implements IUserSpecification {
//传递两个规格书进行and操作
private IUserSpecification left;
private IUserSpecification right;
public AndSpecification(IUserSpecification left, IUserSpecification right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(User user) {
return left.isSatisfiedBy(user) && right.isSatisfiedBy(user);
}
}
//or
import com.sfq.impl.CompositeSpecification;
import com.sfq.impl.IUserSpecification;
public class OrSpecification extends CompositeSpecification implements IUserSpecification {
private IUserSpecification left;
private IUserSpecification right;
public OrSpecification(IUserSpecification left, IUserSpecification right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(User user) {
return left.isSatisfiedBy(user) || right.isSatisfiedBy(user);
}
}
//not
import com.sfq.impl.CompositeSpecification;
import com.sfq.impl.IUserSpecification;
public class NotSpecification extends CompositeSpecification implements IUserSpecification {
private IUserSpecification spec;
public NotSpecification(IUserSpecification spec) {
this.spec = spec;
}
@Override
public boolean isSatisfiedBy(User user) {
return !spec.isSatisfiedBy(user);
}
}
import com.sfq.impl.CompositeSpecification;
public class UserByNameEqual extends CompositeSpecification {
//基准姓名
private String name;
public UserByNameEqual(String name) {
this.name = name;
}
//验证用户是否满足条件
@Override
public boolean isSatisfiedBy(User user) {
return user.getName().equals(name);
}
}
import com.sfq.impl.CompositeSpecification;
public class UserByNameLike extends CompositeSpecification {
//like的标记
private final static String LIKE_FLAG = "%";
//基准的like字符串
private String likeStr;
//构造函数传递基准姓名
public UserByNameLike(String _likeStr){
this.likeStr = _likeStr;
}
//检验用户是否满足条件
public boolean isSatisfiedBy(User user) {
boolean result = false;
String name = user.getName();
//替换掉%后的干净字符串
String str = likeStr.replace("%","");
//是以名字开头,如'国庆%'
if(likeStr.endsWith(LIKE_FLAG) && !likeStr.startsWith(LIKE_FLAG)){
result = name.startsWith(str);
}else if(likeStr.startsWith(LIKE_FLAG) && !likeStr.endsWith(LIKE_FLAG)){
//类似 '%国庆'
result = name.endsWith(str);
}else{
result = name.contains(str);
//类似于'%国庆%'
}
return result;
}
}
import java.util.ArrayList;
import com.sfq.action.User;
import com.sfq.action.UserByNameLike;
import com.sfq.action.UserProvider;
import com.sfq.impl.IUserProvider;
import com.sfq.impl.IUserSpecification;
public class Client {
public static void main(String[] args) {
//初始化一批用户
ArrayList userList = new ArrayList();
userList.add(new User("李国庆", 23));
userList.add(new User("张国庆", 99));
userList.add(new User("国庆五", 10));
userList.add(new User("王大", 1));
//定义用户查找类
IUserProvider userProvider = new UserProvider(userList);
System.out.println("-----名字带国庆的-----");
//定义规格书
IUserSpecification userSpec = new UserByNameLike("%国庆%");
for(User u:userProvider.findUser(userSpec)) {
System.out.println(u);
}
}
}
结果
-----名字带国庆的-----
用户名:李国庆 年龄:23
用户名:张国庆 年龄:99
用户名:国庆五 年龄:10