java设计模式之策略模式

需求:查询年龄大于20岁的用户
查询工资大于5000的用户

准备一个用户实体类

@Data
@AllArgsConstructor
@ToString
public class User {
    private String name;
    private int age;
    private double salary;
}

测试类

@SpringBootTest
class PracticeApplicationTests {
	//准备一个操作的集合模拟查询数据库
    private List<User> users = Arrays.asList(
            new User("张三",12,4000),
            new User("李四",42,3000),
            new User("王五",32,5000),
            new User("赵六",22,6000),
            new User("陈七",52,8000),
    );

	//查询年龄大于20的用户
	public List<User> getUserByAge(List<User> list){
		List<User> users = new LinkedList<User>();
		for (User user : list) {
           if (user.getAge > 20){
               users.add(user);
           }
        }
        return users;
	}
	//查询工资大于5000的用户
	public List<User> getUserBySalary(List<User> list){
		List<User> users = new LinkedList<User>();
		for (User user : list) {
           if (user.getSalary > 5000){
               users.add(user);
           }
        }
        return users;
	}
	//调用这两个方法查看结果
	    @Test
    public void testStrategy(){
        List<User> userByAge = getUserByAge(users);
        for (User user : userByAge) {
            System.out.println(user);
        }
        System.out.println("-------------分割线---------------");
        List<User> userBySalary = getUserBySalary(users);
        for (User user : userBySalary) {
            System.out.println(user);
        }
    }
}

打印结果如下

User(name=李四, age=42, salary=3000.0)
User(name=王五, age=32, salary=5000.0)
User(name=赵六, age=22, salary=6000.0)
-------------分割线---------------
User(name=赵六, age=22, salary=6000.0)

通过观察我们发现上面两个方法只有if( )中的语句不同,其他的完全相同,那么有什么办法优化一下?我们添加一个接口,接口定义行为,我们在接口中定义的行为就是一个方法test,通过test方法来实现对User的过滤功能。再增加两个实现,一个是按照年龄过滤,一个是按照工资过滤

	public interface StrategyFilter {
	    public boolean test(User u);
	}
public class StrategyUserAgeFilter implements StrategyFilter{
    @Override
    public boolean test(User user) {
        return user.getAge() > 20;
    }
}
public class StrategyUserSalaryFilter implements StrategyFilter{
    @Override
    public boolean test(User user) {
        return user.getSalary() > 5000;
    }
}

最终我们的代码是这样

    public List<User> userFilter(List<User> list,StrategyFilter filter){
        List<User> users = new LinkedList<User>();
        for (User u : list) {
            if (filter.test(u)){
                users.add(u);
            }
        }
        return users;
    }
    @Test
    public void testStrategy(){
        List<User> userByAge = userFilter(users, new StrategyUserAgeFilter());
        for (User user : userByAge) {
            System.out.println(user);
        }
        List<User> userBySalary = userFilter(users, new StrategyUserSalaryFilter());
        for (User user : userBySalary ) {
            System.out.println(user);
        }
    }

最终结果

User(name=李四, age=42, salary=3000.0)
User(name=王五, age=32, salary=5000.0)
User(name=赵六, age=22, salary=6000.0)
-------------分割线---------------
User(name=赵六, age=22, salary=6000.0)

上面这就基本上是一个简单的策略模式了,根据需要不同选择不同的策略,这个时候又来了一个需求,说有一个X类,要求通过其中的某个属性过滤,这个时候怎么办呢?其实通过上面的代码我们就基本上已经很清楚了,增加一个泛型即可,因此最终我们的方法变成了下面这样

// 声明一个泛型接口,定义核心方法过滤
public interface StrategyFilter<T> {
    public boolean test(T t);
}
//用户年龄的过滤实现
public class StrategyUserAgeFilter implements StrategyFilter<User>{
    @Override
    public boolean test(User user) {
        return user.getAge() > 20;
    }
}
@Data
@AllArgsConstructor
@ToString
public class People {

    @ApiModelProperty("肤色")
    private String skinColour;

    @ApiModelProperty("体格")
    private Integer physique;

}
//人类肤色的过滤实现
public class StrategyPeopleFilter implements StrategyFilter<People> {
    @Override
    public boolean test(People people) {
        return "黄".equals(people.getSkinColour());
    }
}

等等各种各样的实现都可以自己定义
最终我们调用方法如下

    private List<People> peoples = Arrays.asList(
            new People("黄",12),
            new People("白",22),
            new People("黑",23)
    );
	public <T> List<T> beanFilter(List<T> list,StrategyFilter<T> filter){
        List<T> ts= new LinkedList<T>();
        for (T t : list) {
            if (filter.test(t)){
                users.add(t);
            }
        }
        return ts;
    }
    @Test
    public void testStrategy(){
        List<User> userByAge = beanFilter(users, new StrategyUserAgeFilter());
        for (User user : userByAge) {
            System.out.println(user);
        }
        System.out.println("-------------分割线---------------");
        List<User> userBySalary = beanFilter(users, new StrategyUserSalaryFilter());
        for (User user : userBySalary) {
            System.out.println(user);
        }
        for (People people : beanFilter(peoples, new StrategyPeopleFilter())) {
            System.out.println(people);
        }
         //这样我们每个扩展都要实现接口重写方法,因此也可以用匿名内部类的方式来实现
        List<Dept> depts = beanFilter(Arrays.asList(
                new Dept("财务部"),
                new Dept("研发部"),
                new Dept("行政部")
        ), new StrategyFilter<Dept>() {
            @Override
            public boolean test(Dept dept) {
                return "财务部".equals(dept.getName());
            }
        });
    }

最终结果

User(name=李四, age=42, salary=3000.0)
User(name=王五, age=32, salary=5000.0)
User(name=赵六, age=22, salary=6000.0)
-------------分割线---------------
User(name=赵六, age=22, salary=6000.0)
People(skinColour=黄, physique=12)

我们看到用匿名内部类的时候还是有些内容例如 new StrategyFilter() 那么可以用java8的lambda表达式来简化

@Test
    public void testStrategy(){
        List<User> userByAge = beanFilter(users, new StrategyUserAgeFilter());
        for (User user : userByAge) {
            System.out.println(user);
        }
        System.out.println("-------------分割线---------------");
        List<User> userBySalary = beanFilter(users, new StrategyUserSalaryFilter());
        for (User user : userBySalary) {
            System.out.println(user);
        }
        for (People people : beanFilter(peoples, new StrategyPeopleFilter())) {
            System.out.println(people);
        }
         //这样我们每个扩展都要实现接口重写方法,因此也可以用匿名内部类的方式来实现
        List<Dept> depts = beanFilter(Arrays.asList(
                new Dept("财务部"),
                new Dept("研发部"),
                new Dept("行政部")
        ), new StrategyFilter<Dept>() {
            @Override
            public boolean test(Dept dept) {
                return "财务部".equals(dept.getName());
            }
        });
		//lambda 表达式
		List<Dept> depts1 = beanFilter(Arrays.asList(
                new Dept("财务部"),
                new Dept("研发部"),
                new Dept("行政部")
        ),(dept) -> "财务部".equals(dept.getName()));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值