重构代码为泛型和功能界面 [英] Refactoring code to be Generics and functional interface

查看:180
本文介绍了重构代码为泛型和功能界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个接口可以用来通过Key和Value查找一些统计信息,另一个用于访问一个对象并进行迭代,第一个有以下方法:

  public interface Statistic {

public String getKey();

public Object getValue();

public String getDetails();
}

这里是它的实现:

  public class Collector implements Statistic {

private String key;
private int val;

public Collector(String key,int val){
this.key = key;
this.val = val;
}

public void setValue(int val){
this.val = val;
}

@Override
public String getKey(){
return key;
}

@Override
public Integer getValue(){
return val;
}

@Override
public String getDetails(){
return null;
}
}

另一个具有以下内容:

  public interface StatisticsCollector< T extends Object,S extends Statistic> {

public String getName();

public void visit(T object);

public Iterator< S> calculatedStatistics();
}

这里是它的实现:

  public class CalculateFromObject< K,V>实现StatisticsCollector< Object,Collector> {

EmployeeValidator empValidator = new EmployeeValidator();
StringValidator strValidator = new StringValidator();

@Override
public String getName(){
return null;
}

@Override
public void visit(Object object){
if(object instanceof String){
String str = object.toString() ;

int upperCaseCount = strValidator.upperCaseFreq(str);
strValidator.set.add(new Collector(Upper Case Letters:,upperCaseCount));
int lowerCaseCount = strValidator.lowerCaseFreq(str);
strValidator.set.add(new Collector(Small Case Letters:,lowerCaseCount));
int digitsCount = strValidator.digitFreq(str);
strValidator.set.add(new Collector(Digits Count:,digitsCount));
int wordCount = strValidator.wordFreq(str);
strValidator.set.add(new Collector(Words Count:,wordCount));
int nonWordCount = strValidator.nonWordFreq(str);
strValidator.set.add(new Collector(Non Word Count:,nonWordCount));

} else if(object instanceof Employee){

Employee emp =(Employee)object;
empValidator.salaryValidator(emp);
empValidator.birthDateValidator(emp);
empValidator.birthPlaceValidator(emp);
empValidator.resignationDateValidator(emp);
empValidator.positionValidator(emp);
}
}

@Override
public Iterator< Collector> calculateStatistics(){
return empValidator.set.iterator();
}


}

在我的包我有一个Bean为Employee,它具有很少的属性,如firstName,lastName,salary和position与他们的setter和getter。



我想做一些验证,如得到我雇员人数为x,出生于1990年,并为以下类别进行了验证:

  public class EmployeeValidator {

public Set< Collector> set = new HashSet();

public void salaryValidator(Employee emp){
int count = 0;
//每个收集器包含一个条件(function),key,value(总是递增)
if(emp.getSalary()< 350){
set.add(new Collector 工资低于350JD的员工,++数));
} else if(emp.getSalary()> = 350&& emp.getSalary()< 600){
set.add(new Collector(Employee with salaries between 350JD to 600JD :,++ count));
} else if(emp.getSalary()> = 600&& emp.getSalary()< 1200){
set.add(new Collector(Employee with salary between 600JD and 1200JD ,++ count));
} else if(emp.getSalary()> = 1200){
set.add(new Collector(Employee with salary than 1200JD:,++ count));




public void birthDateValidator(Employee emp){
for(Collector stats:set){
if((员工出生在+ emp.getBirthDate()。getYear()+=).equals(stats.getKey())){
count(stats);
return;
}
}
set.add(new Collector(Employees that born born in+ emp.getBirthDate()。getYear()+=,1));


public void birthPlaceValidator(Employee emp){
for(Collector stats:set){
if((Employees that born born in+ emp。 getBirthPlace()+=).equals(stats.getKey())){
count(stats);
return;
}
}
set.add(new Collector(Employees that born born in+ emp.getBirthPlace()+=,1));
}

public void resignationDateValidator(Employee emp){
for(Collector stats:set){
if((Employees that where Resignation in+ emp。 getResignationDate()。getYear()+=).equals(
stats.getKey())){
count(stats);
return;
}
}
set.add(new Collector(Employees that where Resignation in+ emp.getResignationDate()。getYear()+=,1));


public void positionValidator(Employee emp){
for(Collector stats:set){
if((Employees that占据+ emp.getPosition ()+position =).equals(stats.getKey())){
count(stats);
return;
}
}
set.add(new Collector(Employees that占据+ emp.getPosition()+position =,1));
}

private void count(Collector stats){
int counter = stats.getValue()+ 1;
stats.setValue(counter);
}
}

我有另一个类验证字符串,看看如何许多大写字母有一个字符串,多少小写它有...等



正如你可以看到在CalculateFromObject类中的访问方法im调用所有我的方法做验证,一切都正常,我得到预期的结果,但是我的代码不是很有效率,因为我想让它通用,并使其接受任何类型的对象,我做了很少的尝试,但是im卡住了。 / p>

我已经尝试编写一个名为Conditions的功能界面,它有一种方法可以传递条件,并检查它如下:

  public interface条件{

boolean checkCondition(Object obj);

}

所以有人可以建议什么是最好的方式来改变我的代码是通用的,并且接受例如Student的任何类型的对象,并且通过应用设计模式尽可能的干净?

解决方案

您的课程有很多开销,并且对 POJO的(简单类)。在高级别,您应该执行以下操作:



1)。删除界面统计和类收藏者。他们只是封闭数据。而是创建必要的字段+ getter + setter的POJO Employee 。不要使用'key - value`,给这些字段有意义的名字:

  public class Employee 
{
private String name;
private int id;
私人双重工资;
...
public String getName(){...}
public void setName(..){...}
//其他getters / setters
}

如果需要,创建构造函数



2)看起来你的 Employee 类也是多余的,删除它。使用新的员工代替
3)使用 Collections 框架来存储员工实例的集合。

 `列表与LT;员工> employees = new ArrayList<>(); 
employees.add(new Employee(....)); `

4)。使用验证方法创建接口EmployeeValidator并实现它:



public interface EmployeeValidator {
void validate(List< Employee> employees);
}



5)如果要操作某些统计数据,请创建一个单独的 Statistics class将会对员工的集合进行操作,例如

  public class Statistics {

public double getAvgSalary(List< Employee> employees)
{
double avgSalary = 0;
(员工e:员工){
....
}
}
}


I have two interfaces one can be used to find some statistics by Key and Value and the other is used to visit an object and iterate over it, the first one has the following methods:

public interface Statistic {

    public String getKey();

    public Object getValue();

    public String getDetails();
}

And here is the implementation for it:

public class Collector implements Statistic {

    private String key;
    private int val;

    public Collector(String key, int val) {
        this.key = key;
        this.val = val;
    }

    public void setValue(int val) {
        this.val = val;
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public Integer getValue() {
        return val;
    }

    @Override
    public String getDetails() {
        return null;
    }
}

And the other one has the following:

public interface StatisticsCollector<T extends Object, S extends Statistic> {

    public String getName();

    public void visit(T object);

    public Iterator<S> calculatedStatistics();
}

And here is the implementation for it:

public class CalculateFromObject<K, V> implements StatisticsCollector<Object, Collector> {

    EmployeeValidator empValidator = new EmployeeValidator();
    StringValidator strValidator = new StringValidator();

    @Override
    public String getName() {
        return null;
    }

    @Override
    public void visit(Object object) {
        if (object instanceof String) {
            String str = object.toString();

            int upperCaseCount = strValidator.upperCaseFreq(str);
            strValidator.set.add(new Collector("Upper Case Letters: ", upperCaseCount));
            int lowerCaseCount = strValidator.lowerCaseFreq(str);
            strValidator.set.add(new Collector("Lower Case Letters: ", lowerCaseCount));
            int digitsCount = strValidator.digitFreq(str);
            strValidator.set.add(new Collector("Digits Count: ", digitsCount));
            int wordCount = strValidator.wordFreq(str);
            strValidator.set.add(new Collector("Words Count: ", wordCount));
            int nonWordCount = strValidator.nonWordFreq(str);
            strValidator.set.add(new Collector("Non Word Count: ", nonWordCount));

        } else if (object instanceof Employee) {

            Employee emp = (Employee) object;
            empValidator.salaryValidator(emp);
            empValidator.birthDateValidator(emp);
            empValidator.birthPlaceValidator(emp);
            empValidator.resignationDateValidator(emp);
            empValidator.positionValidator(emp);
        }
    }

    @Override
    public Iterator<Collector> calculatedStatistics() {
        return empValidator.set.iterator();
    }


}

And in my package I have a bean for Employee which has few properties like firstName, lastName, salary and position with their setters and getters.

I would like to do some validations like get me the number of employees which has a salary of x and been born in 1990 and did the following class for these validations:

public class EmployeeValidator {

    public Set<Collector> set = new HashSet<>();

    public void salaryValidator(Employee emp) {
        int count = 0;
        // each collector consist of a condition (function), key, value (always incremented)
        if (emp.getSalary() < 350) {
            set.add(new Collector("Employee with salaries less than 350JD: ", ++count));
        } else if (emp.getSalary() >= 350 && emp.getSalary() < 600) {
            set.add(new Collector("Employee with salaries between 350JD And 600JD: ", ++count));
        } else if (emp.getSalary() >= 600 && emp.getSalary() < 1200) {
            set.add(new Collector("Employee with salaries between 600JD And 1200JD ", ++count));
        } else if (emp.getSalary() >= 1200) {
            set.add(new Collector("Employee with salaries more than 1200JD: ", ++count));
        }

    }

    public void birthDateValidator(Employee emp) {
        for (Collector stats : set) {
            if (("Employees that where born in " + emp.getBirthDate().getYear() + " = ").equals(stats.getKey())) {
                count(stats);
                return;
            }
        }
        set.add(new Collector("Employees that where born in " + emp.getBirthDate().getYear() + " = ", 1));
    }

    public void birthPlaceValidator(Employee emp) {
        for (Collector stats : set) {
            if (("Employees that where born in " + emp.getBirthPlace() + " = ").equals(stats.getKey())) {
                count(stats);
                return;
            }
        }
        set.add(new Collector("Employees that where born in " + emp.getBirthPlace() + " = ", 1));
    }

    public void resignationDateValidator(Employee emp) {
        for (Collector stats : set) {
            if (("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ").equals(
                    stats.getKey())) {
                count(stats);
                return;
            }
        }
        set.add(new Collector("Employees that where Resignation in " + emp.getResignationDate().getYear() + " = ", 1));
    }

    public void positionValidator(Employee emp) {
        for (Collector stats : set) {
            if (("Employees that occupy the " + emp.getPosition() + " position = ").equals(stats.getKey())) {
                count(stats);
                return;
            }
        }
        set.add(new Collector("Employees that occupy the " + emp.getPosition() + " position = ", 1));
    }

    private void count(Collector stats) {
        int counter = stats.getValue() + 1;
        stats.setValue(counter);
    }
}

And I have another class to validate strings and see how many uppercase letters a string has, how many lower case it has...etc

As you can see in the visit method in the CalculateFromObject class im calling all my methods to do the validations, everything is working fine and I am getting the expected results, but my code is not very efficient as I would like to make it generic and make it accept any type of object, I have done few tries but im stuck.

I have tried to write a functional interface called Conditions that has one method that I can pass a condition and check it like the following:

public interface Conditions {

    boolean checkCondition(Object obj);

}

So can someone suggest what is the best way to change my code to be generic and accept any type of objects like Student for example and to be as clean as possible maybe by applying a design pattern?

解决方案

There's a lot of overhead in your classes and misunderstanding of interfaces against POJO's (simple classes). On a high level you should do the following:

1). Remove interface Statistic and class Collectors. They are just incapsulating data. Instead - create a POJO Employee with necessary fields + getters + setters. Don't use 'key-value`, give those fields meaningful names:

public class Employee
{
    private String name;
    private int id;
    private double salary;
        ...
     public String getName() {...}
     public void setName(..) {...}
// other getters / setters
}

Create constructor if needed

2) Looks like your Employee class is also redundant, remove it. Use new Employee instead 3) Use Collections framework to store collections of your employee's instances.

`List<Employee> employees = new ArrayList<>();
employees.add(new Employee(.... )); `

4). Create interface EmployeeValidator with validating methods and implement it:

public interface EmployeeValidator { void validate(List<Employee> employees); }

5) If you want to operate some statistics data, create a separate Statistics class which will operate on collections of employees, e.g.

public class Statistics {

    public double getAvgSalary(List<Employee> employees)
    {
        double avgSalary = 0;
        for (Employee e : employees) {
        ....
        }
    }
}

这篇关于重构代码为泛型和功能界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆