I am a newbie in thinking object oriented solution for a problem, so I am trying to improve. I have tried to implement a quarantine assignment.
Here is a requirement with unit test cases. I am trying to make this assignment scalable as much as possible with a good object oriented design.
public class QuarantineTest {
private Quarantine quarantine;
@Before
public void setUp() {
// The responsibility of the Quarantine object is to simulate diseases on a group of patients.
// It is initialized with a list of patients' health status, separated by a comma.
// Each health status is described by one or more characters
// (in the test below, we will always have only one disease / patient)
// The characters mean:
// H : Healthy
// F : Fever
// D : Diabetes
// T : Tuberculosis
quarantine = new Quarantine("F,H,D,D,D,H,T");
// Quarantine provides medicines to the patients, but can not target a specific group of patient.
// The same medicines are always given to all the patients.
// Then Quarantine can provide a report with this format:
// "F:1 H:2 D:0 T:1 X:3"
// Report give the number of patients that have the given disease.
// X means Dead
}
@Test
public void beforeTreatment() throws Exception {
assertEquals("F:1 H:2 D:3 T:1 X:0", quarantine.report());
}
// people died in the Diabetes
@Test
public void noTreatment() throws Exception {
quarantine.wait40Days();
// diabetics die without insulin
assertEquals("F:1 H:2 D:0 T:1 X:3", quarantine.report());
}
// feaver is cured
// people died in the Diabetes
@Test
public void aspirin() throws Exception {
quarantine.aspirin();
quarantine.wait40Days();
// aspirin cure Fever
assertEquals("F:0 H:3 D:0 T:1 X:3", quarantine.report());
}
@Test
public void antibiotic() throws Exception {
quarantine.antibiotic();
quarantine.wait40Days();
// antibiotic cure Tuberculosis
// but healthy people catch Fever if mixed with insulin.
assertEquals("F:1 H:3 D:0 T:0 X:3", quarantine.report());
}
@Test
public void insulin() throws Exception {
quarantine.insulin();
quarantine.wait40Days();
// insulin prevent diabetic subject from dying, does not cure Diabetes,
assertEquals("F:1 H:2 D:3 T:1 X:0", quarantine.report());
}
@Test
public void antibioticPlusInsulin() throws Exception {
quarantine.antibiotic();
quarantine.insulin();
quarantine.wait40Days();
// if insulin is mixed with antibiotic, healthy people catch Fever
assertEquals("F:3 H:1 D:3 T:0 X:0", quarantine.report());
}
@Test
public void paracetamol() throws Exception {
quarantine.paracetamol();
quarantine.wait40Days();
// paracetamol heals fever
assertEquals("F:0 H:3 D:0 T:1 X:3", quarantine.report());
}
@Test
public void paracetamolAndAspirin() throws Exception {
quarantine.paracetamol();
quarantine.aspirin();
quarantine.wait40Days();
// paracetamol kills subject if mixed with aspirin
assertEquals("F:0 H:0 D:0 T:0 X:7", quarantine.report());
}
}
This is what I have implemented:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class Quarantine {
LinkedHashMap<PatientType,Integer> patientInfoMap = new LinkedHashMap<>();
private ArrayList<Medicines> appliedTreatementList = new ArrayList<>();
ArrayList<ITreatment> treatementRepository = new ArrayList<>();
static int treatedTBPatientCount=0;
static boolean isInsulineInjected = false;
public Quarantine(String subjects) {
String[] patientArr = subjects.split(",");
for(String disease :patientArr){
int patientCount = patientInfoMap.get(PatientType.getType(disease)) != null ? patientInfoMap.get(PatientType.getType(disease)):0;
patientInfoMap.put(PatientType.getType(disease),++patientCount);
}
patientInfoMap.put(PatientType.DEAD,0);
}
public String report() {
try {
final String[] result = {""};
patientInfoMap.forEach((k, v) -> result[0] += PatientType.getValue(k) + ":" + v.toString() + " ");
return result[0].trim();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void wait40Days() {
for(ITreatment treatment : treatementRepository){
treatment.treat(patientInfoMap,appliedTreatementList);
}
if(!isInsulineInjected){
dieDiabticPatient();
}
}
private void dieDiabticPatient() {
patientInfoMap.put(PatientType.DEAD, patientInfoMap.get(PatientType.DIABATIC));
patientInfoMap.put(PatientType.DIABATIC, 0);
}
public void aspirin() {
appliedTreatementList.add(Medicines.ASPIRIN);
treatementRepository.add(new TreatmentAspirin());
}
public void antibiotic() {
appliedTreatementList.add(Medicines.ANTIBIOTIC);
treatementRepository.add(new TreatmentAntibiotic());
}
public void insulin() {
appliedTreatementList.add(Medicines.INSULIN);
treatementRepository.add(new TreatmentInsulin());
}
public void paracetamol() {
appliedTreatementList.add(Medicines.PARACETOL);
treatementRepository.add(new TreatmentParacetamol());
}
}
TreatmentAntibiotic class:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class TreatmentAntibiotic implements ITreatment{
@Override
public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList) {
if(appliedTreatementList.contains(Medicines.ANTIBIOTIC)){
Quarantine.isInsulineInjected = false;
LinkedHashMap<PatientType, Integer> map = patientInfoMap;
Quarantine.treatedTBPatientCount = map.get(PatientType.TUBERCLOSIS);
map.put(PatientType.HEALTHY, map.get(PatientType.HEALTHY) + map.get(PatientType.TUBERCLOSIS));
map.put(PatientType.TUBERCLOSIS, 0);
}
}
}
ITreatment interface:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
interface ITreatment {
abstract public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList);
}
enum class:
package quarantine;
enum Medicines {
INSULIN,
ANTIBIOTIC,
PARACETOL,
ASPIRIN
}
PatientType class:
package quarantine;
public enum PatientType {
DEAD("X"),
DIABATIC("D"),
FEVER("F"),
TUBERCLOSIS("T"),
HEALTHY("H");
private final String disease;
PatientType(String disease) {
this.disease = disease;
}
public static String getValue(PatientType patientType)
{
for (PatientType type : PatientType.values())
if (type.equals(patientType))
return type.disease;
return null;
}
public static PatientType getType(String diseaseType)
{
for (PatientType type : PatientType.values())
if (type.disease.equals(diseaseType))
return type;
return null;
}
}
TreatmentAntibiotic class:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class TreatmentAntibiotic implements ITreatment{
@Override
public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList) {
if(appliedTreatementList.contains(Medicines.ANTIBIOTIC)){
Quarantine.isInsulineInjected = false;
LinkedHashMap<PatientType, Integer> map = patientInfoMap;
Quarantine.treatedTBPatientCount = map.get(PatientType.TUBERCLOSIS);
map.put(PatientType.HEALTHY, map.get(PatientType.HEALTHY) + map.get(PatientType.TUBERCLOSIS));
map.put(PatientType.TUBERCLOSIS, 0);
}
}
}
TreatmentAspirin class:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class TreatmentAspirin implements ITreatment{
@Override
public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList) {
if(appliedTreatementList.contains(Medicines.ASPIRIN)){
LinkedHashMap<PatientType, Integer> map = patientInfoMap;
if(appliedTreatementList.contains(Medicines.PARACETOL)){
Quarantine.isInsulineInjected = true; //Because They are Dead
map.put(PatientType.DEAD, map.get(PatientType.DEAD) + map.get(PatientType.FEVER) + map.get(PatientType.HEALTHY) + map.get(PatientType.DIABATIC) + map.get(PatientType.TUBERCLOSIS));
map.put(PatientType.HEALTHY, 0);
map.put(PatientType.DIABATIC, 0);
map.put(PatientType.TUBERCLOSIS, 0);
}else{
Quarantine.isInsulineInjected = false;
map.put(PatientType.HEALTHY, map.get(PatientType.HEALTHY) + map.get(PatientType.FEVER));
map.put(PatientType.FEVER, 0);
}
}
}
}
TreatmentInsulin class:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class TreatmentInsulin implements ITreatment{
@Override
public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList) {
if(appliedTreatementList.contains(Medicines.INSULIN)){
LinkedHashMap<PatientType, Integer> map = patientInfoMap;
Quarantine.isInsulineInjected = true;
if(appliedTreatementList.contains(Medicines.ANTIBIOTIC)){
map.put(PatientType.FEVER, map.get(PatientType.HEALTHY) + map.get(PatientType.FEVER)-Quarantine.treatedTBPatientCount);
map.put(PatientType.HEALTHY, Quarantine.treatedTBPatientCount);
}
}
}
}
TreatmentParacetamol class:
package quarantine;
import java.util.ArrayList;
import java.util.LinkedHashMap;
public class TreatmentParacetamol implements ITreatment{
@Override
public void treat(LinkedHashMap<PatientType, Integer> patientInfoMap, ArrayList<Medicines> appliedTreatementList) {
if(appliedTreatementList.contains(Medicines.PARACETOL)){
Quarantine.isInsulineInjected = false;
LinkedHashMap<PatientType, Integer> map = patientInfoMap;
map.put(PatientType.HEALTHY, map.get(PatientType.HEALTHY) + map.get(PatientType.FEVER));
map.put(PatientType.FEVER, 0);
}
}
}
The use of map at all places and using static members is looking awkward, so please suggest how I can improve this code as well as object-oriented thinking.