0

키와 값으로 일부 통계를 찾는 데 사용할 수있는 인터페이스와 오브젝트를 방문하여 반복하는 데 사용되는 인터페이스가 두 개 있습니다. 첫 번째 메소드는 다음과 같습니다.코드를 리팩토링하여 일반 및 기능 인터페이스

public interface Statistic { 

    public String getKey(); 

    public Object getValue(); 

    public String getDetails(); 
} 

그리고 여기가 그것에 대한 구현 :

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

    public String getName(); 

    public void visit(T object); 

    public Iterator<S> calculatedStatistics(); 
} 
:

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 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(); 
    } 


} 

그리고 내 패키지에 나는 그들의 세터와 게터와 이름, 성, 급여 및 위치 등의 몇 가지 특성을 가지고 직원을위한 콩이있다.

내가 나에게 X의 급여를 가지고 있으며, 1990 년에 태어 났으며, 이러한 검증을위한 다음의 클래스했던 한 직원의 수를 얻을 같은 몇 가지 검증을 할 싶습니다

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); 
    } 
} 

을 그리고 다른 클래스가 문자열의 유효성을 검사하고 문자열에 포함 된 대문자의 수, 소문자가 몇 개인지 등을 확인합니다.

CalculateFromObject 클래스의 visit 메서드에서 확인할 수 있듯이 모든 메서드에서 유효성 검사를 수행하므로 모든 잘 작동하고 예상되는 결과를 얻고 있지만 코드를 매우 효율적으로 만들지 않아서 ge를 만들고 싶습니다. neric과 그것이 어떤 타입의 객체라도 받아 들일 수 있도록해라, 나는 거의 시도하지 않았다. 그러나 메신저는 붙였다.

은 내가 조건을 통과하고처럼 확인할 수있는 하나 개의 방법이있는 기능적인 인터페이스라는 조건을 작성하는 시도 다음

public interface Conditions { 

    boolean checkCondition(Object obj); 

} 

그래서 누군가가 변경할 수있는 최선의 방법이 무엇인지 제안 할 수 있습니다 내 코드를 일반화하고 Student와 같은 모든 유형의 객체를 허용하고 가능하면 디자인 패턴을 적용하여 가능한 한 깨끗하게 처리 할 수 ​​있습니까?

답변

1

클래스에 많은 오버 헤드가 있고 POJO's (간단한 클래스)에 대한 인터페이스 오해가 있습니다. 높은 수준에서 다음을 수행해야합니다.

1). 인터페이스 Statistic 및 클래스 Collectors을 제거하십시오. 그들은 단지 데이터를 캡슐화하고 있습니다. 대신 필요한 필드 + getters + setters가있는 POJO Employee을 만듭니다. '키 - 값'을 사용하지 마십시오, 그 필드를 의미있는 이름을 부여 :

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

하는

2

를 필요한 경우) 생성자를 작성 보이는 당신의 Employee 클래스는 중복과 같이 제거합니다. 대신 새로운 직원을 사용하십시오 3) Collections 프레임 워크를 사용하여 직원의 인스턴스 모음을 저장하십시오.

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

4).그것을 방법 유효성 검증 인터페이스 EmployeeValidator을 만들고 구현 :

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

5) 당신은 몇 가지 통계 데이터를 조작하려는 경우, 예를 들어, 직원의 컬렉션에서 작동하는 별도의 Statistics 클래스를 생성 당신이 인터페이스를 오용하고 있다는

public class Statistics { 

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

나는 인터페이스 통계 및 작업이 그들에게 –

+0

주요 아이디어를 구현하는 것입니다으로 콜렉터입니다 제거 기운 다. 클래스를 리 팩터링하고 필요한 것들을 남겨 두십시오. –

+0

좋아, 그게 무슨 뜻인지 알 겠어. 이제 어떻게하면 일반화 할 수 있고, Student 객체에서 같은 것을 쉽게 구현할 수 있을까? –