本文节选自《设计模式就该这样学》

1 规格模式的定义

规格模式(Specification Pattern)能够认为是组合模式的一种扩大。很多时候程序中的某些条件决定了业务逻辑,这些条件就能够抽离进去以某种关系(与、或、非)进行组合,从而灵便地对业务逻辑进行定制。另外,在查问、过滤等利用场合中,通过预约义多个条件,而后应用这些条件的组合来解决查问或过滤,而不是应用逻辑判断语句来解决,能够简化整个实现逻辑。
这里的每个条件都是一个规格,多个规格(条件)通过串联的形式以某种逻辑关系造成一个组合式的规格。规格模式属于结构型设计模式。

2 规格模式的利用场景

规格模式次要实用于以下利用场景。

(1)验证对象,测验对象自身是否满足某些业务要求或者是否曾经为实现某个业务指标做好了筹备。

(2)从汇合中抉择合乎特定业务规定的对象或对象子集。

(3)指定在创立新对象的时候必须要满足某种业务要求。

3 规格模式的UML类图

规格模式的UML类图如下图所示。

由上图能够看到,规格模式次要蕴含6个角色。

(1)形象规格书(Specification):对规格书的形象定义。

(2)组合规格书(CompositeSpecification):个别设计为抽象类,对规格书进行与或非操作,实现and()、or()、not()办法,在办法中关联子类,因为子类为固定类,所以父类能够进行关联。

(3)与规格书(AndSpecification):对规格书进行与操作,实现isSatisfiedBy()办法。

(4)或规格书(OrSpecification):对规格书进行或操作,实现isSatisfiedBy()办法。

(5)非规格书(NotSpecification):对规格书进行非操作,实现isSatisfiedBy()办法。

(6)业务规格书(BizSpecification):实现isSatisfiedBy()办法,对业务进行判断,一个类为一种判断形式,可进行扩大。

4 规格模式的通用写法

以下是规格模式的通用写法。

public class Client {    public static void main(String[] args) {        //待剖析的对象        List<Object> list = new ArrayList<Object>();        //定义两个业务规格书        ISpecification spec1 = new BizSpecification("a");        ISpecification spec2 = new BizSpecification("b");        //规格调用        for (Object o : list) {            if(spec1.and(spec2).isSatisfiedBy(o)){  //如果o满足spec1 && spec2                System.out.println(o);            }        }    }    //形象规格书    interface ISpecification {        //候选者是否满足条件        boolean isSatisfiedBy (Object candidate) ;        //and操作        ISpecification and (ISpecification spec);        //or操作        ISpecification or (ISpecification spec);        //not操作        ISpecification not ();    }    //组合规格书    static abstract class CompositeSpecification implements ISpecification {        //是否满足条件由子类实现        public abstract boolean isSatisfiedBy (Object candidate) ;        //and操作        public ISpecification and (ISpecification spec) {            return new AndSpecification(this, spec);        }        //or操作        public ISpecification or(ISpecification spec) {            return new OrSpecification(this, spec);        }        //not操作        public ISpecification not() {            return new NotSpecification(this);        }    }    //与规格书    static class AndSpecification extends CompositeSpecification {        //传递两个规格书进行and操作        private ISpecification left;        private ISpecification right;        public AndSpecification(ISpecification left, ISpecification right) {            this.left = left;            this.right = right;        }                //进行and运算        public boolean isSatisfiedBy(Object candidate) {            return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate);        }    }    static class OrSpecification extends CompositeSpecification {        //传递两个规格书进行or操作        private ISpecification left;        private ISpecification right;        public OrSpecification(ISpecification left, ISpecification right) {            this.left= left;            this.right = right;        }        //进行or运算        public boolean isSatisfiedBy(Object candidate) {            return left.isSatisfiedBy(candidate) || right.isSatisfiedBy(candidate);        }    }    static class NotSpecification extends CompositeSpecification {        //传递两个规格书进行非操作        private ISpecification spec;        public NotSpecification(ISpecification spec) {            this.spec = spec;        }        //进行not运算        public boolean isSatisfiedBy(Object candidate) {            return !spec.isSatisfiedBy(candidate);        }    }    //业务规格书    static class BizSpecification extends CompositeSpecification {        //基准对象,如姓名等,也能够是int等类型        private String obj;        public BizSpecification(String obj) {            this.obj = obj;        }        //判断是否满足要求        public boolean isSatisfiedBy(Object candidate){            //依据基准对象判断是否合乎            return true;        }    }}

5 规格模式的长处

规格模式十分奇妙地实现了对象筛选性能,适宜在多个对象中筛选查找,或者业务规定不适于放在任何已有实体或值对象中,而且规定变动和组合会覆盖对象的根本含意的状况。

6 规格模式的毛病

规格模式中有一个很重大的问题就是父类依赖子类,这种情景只有在十分明确不会发生变化的场景中存在,它不具备扩展性,是一种固化而不可变动的构造。个别在面向对象设计中应该尽量避免。

关注微信公众号『 Tom弹架构 』回复“设计模式”可获取残缺源码。

【举荐】Tom弹架构:30个设计模式实在案例(附源码),挑战年薪60W不是梦
本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我高兴!
如果本文对您有帮忙,欢送关注和点赞;如果您有任何倡议也可留言评论或私信,您的反对是我保持创作的能源。关注微信公众号『 Tom弹架构 』可获取更多技术干货!