设计模式之规格模式

设计模式之规格模式

  • 23中模式之外的新模式

简介

在一系列对象中根据条件搜索!类似sql,但不同的是从内存中的对象进行搜索
具体类似于LINQ(Language Integrated Query)语言集成查询

初步实践

1.创建一个接口,实现按照某种条件筛选:IUserProvider
2.实现以上接口:UserProvider,通过具体的对象类进行抽象方法的实现(例如:遍历实体类数组,进行判断,然后返回结果数组或列表)
3.实现具体对象,类似User实体类
4.实现场景类,初始化一个拥有User的数组或列表,实例化UserProvider,并使用相关方法,获取结果

  • 请注意以上实现,我们可以发现一旦业务发生变更,我们需要改对应的接口方法、需要实现对应的接口,很不容易进行扩展。

  • 第二种:那么我们是否可以将对应的搜索条件进行封装,创建一个接口:IUserSpecification,定义是否满足的方法,返回bool值,这样就可以在多种条件下(业务变更等),进行无缝扩展。只用实现该接口,就可以扩展多个条件类。

  • 对于类似于sql的多个条件查询下,在数据量大的情况下容易造成性能较差,因为需要经过好多轮循环

  • 第三种:可以知道一般条件组合,基本离不开与或非、这三种模式是固定的,我们可以通过这三种模式进行统一的条件封装。

    1.我们创建一个条件规格接口:IUserSpecification,实现判断是否满足,返回bool值
    2.创建一个抽象类实现IUserSpecification:ComposionSpecificaiton,并且通过模板方法实现与或非三种条件规格的生成,具体接口的实现由具体类来实现。此抽象类依赖于具体的实现(请按照实际情况分析,不要死学)
    3.继承ComposionSpecificaiton,实现具体的判断方法
    4.在场景类中,通过条件规格的实现类,使用与或非方法对多个条件进行封装,然后进行计算

第三种方法最优,使用了组合模式、策略模式、模板模式这三种模式组合成了规格模式。

类图

第二种类图

第二种类图

第三种类图

第三种类图

以下为代码

  • 定义一个用户:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    package com.bj.hz.specification.very;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-18
    * @time: 9:48 PM
    */
    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 "User{" +
    "name='" + name + '\'' +
    ", age=" + age +
    '}';
    }
    }
  • 定义一个查询提供类接口以及实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.bj.hz.specification.very;


import java.util.ArrayList;

/**
* Created with hzz
* Description:
*
* @author: huangzhe
* @date: 2018-07-18
* @time: 10:07 PM
*/
public interface IUserProvider {
ArrayList<User> findUser(IUserSpecification specification);
}
  • 提供实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    package com.bj.hz.specification.very;



    import java.util.ArrayList;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-18
    * @time: 10:09 PM
    */
    public class UserProvider implements IUserProvider {

    private ArrayList<User> users;

    public UserProvider(ArrayList<User> users) {
    this.users = users;
    }

    @Override
    public ArrayList<User> findUser(IUserSpecification specification) {
    ArrayList<User> result=new ArrayList<>();
    for (User u:users){
    if (specification.isSatisfiedBy(u)){
    result.add(u);
    }
    }
    return result;
    }
    }
  • 规格条件接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package com.bj.hz.specification.very;

    /**
    * Created with hzz
    * Description:为了适应未来变化的需求,将运算封装到接口之内
    *
    * @author: huangzhe
    * @date: 2018-07-18
    * @time: 10:02 PM
    */
    public interface IUserSpecification {
    public boolean isSatisfiedBy(User user);
    }
  • 组合模式的接口,其实可以定义三个装饰器(请自行想象)分别实现 与或非

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    package com.bj.hz.specification.very;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-19
    * @time: 9:06 AM
    */
    public abstract class AbstractComposition implements IUserSpecification {



    public IUserSpecification and(IUserSpecification userSpecification){
    return new AndSpecification(this,userSpecification);
    }

    public IUserSpecification or(IUserSpecification userSpecification){
    return new OrSpecification(this,userSpecification);
    }
    public IUserSpecification not(IUserSpecification userSpecification){
    return new NotSpecification(this);
    }

    }
  • 分别是与或非实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bj.hz.specification.very;

/**
* Created with hzz
* Description:
*
* @author: huangzhe
* @date: 2018-07-19
* @time: 9:08 AM
*/
public class AndSpecification extends AbstractComposition {

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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bj.hz.specification.very;

/**
* Created with hzz
* Description:
*
* @author: huangzhe
* @date: 2018-07-19
* @time: 9:09 AM
*/
public class OrSpecification extends AbstractComposition {

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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.bj.hz.specification.very;

/**
* Created with hzz
* Description:
*
* @author: huangzhe
* @date: 2018-07-19
* @time: 9:10 AM
*/
public class NotSpecification extends AbstractComposition {

private IUserSpecification userSpecification;

public NotSpecification(IUserSpecification userSpecification) {
this.userSpecification = userSpecification;
}

@Override
public boolean isSatisfiedBy(User user) {
return !userSpecification.isSatisfiedBy(user);
}
}
  • 根据名称查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.bj.hz.specification.very;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-19
    * @time: 9:29 AM
    */
    public class FindByNameSpecification extends AbstractComposition {

    private String name;

    public FindByNameSpecification(String name) {
    this.name = name;
    }

    @Override
    public boolean isSatisfiedBy(User user) {
    return user.getName().equals(name);
    }
    }
  • 根据大于给定的年龄查询

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.bj.hz.specification.very;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-19
    * @time: 9:31 AM
    */
    public class FindByAgeThanSpecification extends AbstractComposition {

    private int age;

    public FindByAgeThanSpecification(int age) {
    this.age = age;
    }

    @Override
    public boolean isSatisfiedBy(User user) {
    return user.getAge()>age;
    }
    }
  • 场景类具体实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    package com.bj.hz.specification.very;




    import java.util.ArrayList;

    /**
    * Created with hzz
    * Description:
    *
    * @author: huangzhe
    * @date: 2018-07-18
    * @time: 10:12 PM
    */
    public class Client {
    public static void main(String[] args) {
    ArrayList<User> users = new ArrayList<>();
    users.add(new User("121", 3));
    users.add(new User("犁牛", 10));
    users.add(new User("测试", 18));
    users.add(new User("hah", 16));
    users.add(new User("黄啦啦", 19));
    users.add(new User("吴啦啦", 20));
    System.out.println("========年龄大于16的==========");
    IUserProvider userProvider=new UserProvider(users);
    for (User user:userProvider.findUser(new FindByNameSpecification("hah").and(new FindByAgeThanSpecification(14)))){
    System.out.println(user);
    }

    }
    }
坚持原创技术分享,您的支持将鼓励我继续创作!