设计模式之规格模式
- 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
43package 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 | package com.bj.hz.specification.very; |
提供实现
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
33package 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
13package 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
26package 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 | package com.bj.hz.specification.very; |
1 | package com.bj.hz.specification.very; |
1 | package com.bj.hz.specification.very; |
根据名称查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package 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
23package 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
32package 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);
}
}
}