新设计模式——规格模式

规格模式

规格模式(Specification Pattern):它是组合模式的一种特殊应用。同时,每个规格书都是一个策略,它完成了一系列逻辑的封装。

新设计模式——规格模式_第1张图片

抽象规格书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 list = new ArrayList(); 
        //定义两个业务规格书 
        ISpecification spec1 = new BizSpecification(new Object()); 
        ISpecification spec2 = new BizSpecification(new Object()); 
        //规则的调用 
        for(Object obj:list){ 
            if(spec1.and(spec2).isSatisfiedBy(obj)){ //and操作 
                System.out.println(obj); 
            } 
        } 
    } 
}  
   

规格模式的实例

查找出姓名中包含国庆”两个字的用户,这在关系型数据库中很容易实现,但是在对象群中怎么实现这样的查询呢?

新设计模式——规格模式_第2张图片

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;
	}
}

 

新设计模式——规格模式_第3张图片

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

 

你可能感兴趣的:(设计模式)