对构造器参数问题的思考

删除回忆录丶 提交于 2019-12-15 09:43:27

前言

构造器的问题应该还是比较重要的,因为我们要设置合理的构造函数暴露出来生成对象。

在我看来,构造器的设置还是需要慎重考虑的,所以以我愚见,结合自己写过的一些代码,对这个问题进行一下分析。

设计模式之——单例模式

(下面的代码为懒汉式、线程非安全)

public class MedicineInfoMapper implements IFileSerialization<AllMedicinesMap> {

    private MedicineInfoMapper() {}

    private static MedicineInfoMapper mapper;

    /**
     * 获取单例
     * @return 单例
     */
    public static MedicineInfoMapper getInstance() {
        if (mapper == null) {
             mapper = new MedicineInfoMapper();
        }
        return mapper;
    }

    /**
     * 反序列化从文件中读取PatientList的序列化对象
     */
    @Override
    public AllMedicinesMap readObject() {
        try (ObjectInputStream ois = new ObjectInputStream(
                new FileInputStream(ALL_MEDICINES_FILENAME))) {
            AllMedicinesMap medicinesMap = (AllMedicinesMap)ois.readObject();
            return medicinesMap;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 序列化对象
     */
    @Override
    public void writeObject(AllMedicinesMap object) {
        try (ObjectOutputStream oos = new ObjectOutputStream(
                new FileOutputStream(ALL_MEDICINES_FILENAME))) {
            oos.writeObject(object);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

不应暴露构造器

这种情况一般适用于工具类/常量类这样的类,不适合(也没必要)生成实例。

下面是常量类,我们暴露出静态常量交给整个工程调用:

public class Constant {

    /**
     * 不允许被实例化
     */
    private Constant() {}

    //...
    public static final ...;
    
}

下面是纯粹的工具类,不应该被实例化,暴露出必要的public static的方法就OK:

public class TimeCalculator {

    //工具类,不允许被实例化
    private TimeCalculator() {}
    
    /**
     * 根据两个时间计算岁数
     * @param nowTime
     * @param oldTime
     * @return
     */
    public static int calculateAge(Calendar nowTime, Calendar oldTime) {
        int age = nowTime.get(Calendar.YEAR) - oldTime.get(Calendar.YEAR);
        if (nowTime.get(Calendar.MONTH) < oldTime.get(Calendar.MONTH)) {
            age--;
        } else if (nowTime.get(Calendar.MONTH) == oldTime.get(Calendar.MONTH) &&
                nowTime.get(Calendar.DATE) < oldTime.get(Calendar.DATE)) {
            age--;
        }
        return age;
    }

    //...

}

设计模式之——工厂模式

public class ResultGenerator {
    
    private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";

    private ResultGenerator() {}

    public static Result genSuccessResult() {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMessage(DEFAULT_SUCCESS_MESSAGE);
    }

    public static Result genSuccessResult(Object data) {
        return new Result()
                .setCode(ResultCode.SUCCESS)
                .setMessage(DEFAULT_SUCCESS_MESSAGE)
                .setData(data);
    }

    public static Result genFailResult(String message) {
        return new Result()
                .setCode(ResultCode.FAIL)
                .setMessage(message);
    }

}

懒得写,完全用默认的构造器

这个比较常见(特别是初学者),编写的类不设计构造器,直接new就完事,就不贴代码了……
emmm还是示意一下吧:

public class DefaultConstructorTest {

    public static void main(String[] args) {
        DefaultConstructorTest obj = new DefaultConstructorTest();
    }

}

直接梭哈,把全部的可用属性全加上

这种也行,干脆全加上,爱咋咋地

import java.io.Serializable;

/**
 * 医生类
 */
public class Doctor implements Serializable {

    /**
     * 默认序列化UID
     */
    private static final long serialVersionUID = 1L;

    /**
     * 医生ID
     */
    private Integer doctorId;

    /**
     * 医生登录名
     */
    private String userName;

    /**
     * 医生账户密码
     */
    private String password;

    /**
     * 医生真实姓名
     */
    private String name;

    /**
     * 医生所在科室
     */
    private String department;

    /**
     * 医生职称信息(主任医师、副主任医师、主治医师、住院医师)
     */
    private String title; 

    /**
     * 是否参与排班
     */
    private Boolean isOnline;

    public Doctor(Integer doctorId, String userName, String password, String name, String department, String title,
            Boolean isOnline) {
        super();
        this.doctorId = doctorId;
        this.userName = userName;
        this.password = password;
        this.name = name;
        this.department = department;
        this.title = title;
        this.isOnline = isOnline;
    }

    public Integer getDoctorId() {
        return doctorId;
    }

    public void setDoctorId(Integer doctorId) {
        this.doctorId = doctorId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Boolean getIsOnline() {
        return isOnline;
    }

    public void setIsOnLine(Boolean isOnline) {
        this.isOnline = isOnline;
    }
    
}

在构造器里进行一些处理再得到结果

比如下面的代码,有这样一句: this.patientAge = TimeCalculator.calculateAge(patientBirthday); ,就是调用了外部方法,利用已有参数进行处理得到值再赋给属性:

public class Patient implements IList<RegisterInfo>, Serializable {
    
    /**
     * 序列化
     */
    private static final long serialVersionUID = 1L;
    
    /**
     * 患者ID
     */
    private Integer patientId;
    
    /**
     * 患者姓名
     * (这是必填项)
     */
    private String patientName;
    
    /**
     * 患者性别
     * (这是必填项)
     */
    private String patientSex;

    /**
     * 患者出生日期
     * (应该是年龄和出生日期填一个,另一个自动计算)
     * 但是为了便于处理,我们只让用户输入出生日期
     */
    private Long patientBirthday;
    
    /**
     * 患者年龄
     * (由计算得到,不需要填)
     */
    private Integer patientAge;

    /**
     * 患者身份证号(末尾有x的情况也需要考虑)
     * 这个很重要,是区分不同患者身份的依据
     * 一定是18位的
     * 正则表达式是这样的
     * "^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$"
     */
    private String patientIDNumber;
    
    /**
     * 患者的家庭住址
     */
    private String patientAddress;
    
    /**
     * 患者的挂号历史
     * 用List储存
     */
    private List<RegisterInfo> registerInfoList;
    
    /**
     * 患者收费记录
     */
    private AllChargeItemsList chargeInfo;
    
    /**
     * 患者被开药记录
     */
    private AllPrescriptionsMap prescriptionMap;

    public Patient(Integer patientId, String patientName, String patientSex,
            Long patientBirthday, String patientIDNumber,
            String patientAddress, List<RegisterInfo> registerInfoList,
            AllChargeItemsList chargeInfo, AllPrescriptionsMap prescriptionMap) {
        super();
        this.patientId = patientId;
        this.patientName = patientName;
        this.patientSex = patientSex;
        this.patientBirthday = patientBirthday;
        this.patientAge = TimeCalculator.calculateAge(patientBirthday);
        this.patientIDNumber = patientIDNumber;
        this.patientAddress = patientAddress;
        this.registerInfoList = registerInfoList;
        this.chargeInfo = chargeInfo;
        this.prescriptionMap = prescriptionMap;
    }

    @Override
    public Boolean add(RegisterInfo item) {
        // TODO Auto-generated method stub
        if (item == null) {
            return false;
        } else if (getElement(item.getRegisterId()) != null) {
            return false;
        }
        registerInfoList.add(item);
        return true;
    }

    @Override
    public Boolean remove(RegisterInfo item) {
        if (item == null) {
            return false;
        }
        RegisterInfo searchItem = getElement(item.getRegisterId());
        if (searchItem == null) {
            return false;
        }
        registerInfoList.remove(searchItem);
        return true;
    }

    @Override
    public RegisterInfo getElement(Integer index) {
        RegisterInfo registerInfo = null;
        for (RegisterInfo item : registerInfoList) {
            if (item.getRegisterId() != null && index.equals(item.getRegisterId())) {
                registerInfo = item;
                break;
            }
        }
        return registerInfo;
    }

    @Override
    public List<RegisterInfo> getList() {
        return registerInfoList;
    }

    @Override
    public Integer getSize() {
        if (registerInfoList != null) {
            return registerInfoList.size();
        }
        return -1;
    }

    public Integer getPatientId() {
        return patientId;
    }

    public void setPatientId(Integer patientId) {
        this.patientId = patientId;
    }

    public String getPatientName() {
        return patientName;
    }

    public void setPatientName(String patientName) {
        this.patientName = patientName;
    }

    public String getPatientSex() {
        return patientSex;
    }

    public void setPatientSex(String patientSex) {
        this.patientSex = patientSex;
    }

    public Long getPatientBirthday() {
        return patientBirthday;
    }

    public void setPatientBirthday(Long patientBirthday) {
        this.patientBirthday = patientBirthday;
    }
    
    public Integer getPatientAge() {
        return patientAge;
    }

    public String getPatientIDNumber() {
        return patientIDNumber;
    }

    public void setPatientIDNumber(String patientIDNumber) {
        this.patientIDNumber = patientIDNumber;
    }
    

    public String getPatientAddress() {
        return patientAddress;
    }

    public void setPatientAddress(String patientAddress) {
        this.patientAddress = patientAddress;
    }

    public List<RegisterInfo> getRegisterInfoList() {
        return registerInfoList;
    }

    public void setRegisterInfoList(List<RegisterInfo> registerInfoList) {
        this.registerInfoList = registerInfoList;
    }

    /**
     * 调用util包里的方法
     * @param patientBirthday
     * @return
     */
    public Integer getAge(Long patientBirthday) {
        return TimeCalculator.calculateAge(patientBirthday);
    }

    public AllChargeItemsList getChargeInfo() {
        return chargeInfo;
    }

    public void setChargeInfo(AllChargeItemsList chargeInfo) {
        this.chargeInfo = chargeInfo;
    }

    public AllPrescriptionsMap getPrescriptionMap() {
        return prescriptionMap;
    }

    public void setPrescriptionMap(AllPrescriptionsMap prescriptionMap) {
        this.prescriptionMap = prescriptionMap;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((patientIDNumber == null) ? 0 : patientIDNumber.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Patient other = (Patient) obj;
        if (patientIDNumber == null) {
            if (other.patientIDNumber != null)
                return false;
        } else if (!patientIDNumber.equals(other.patientIDNumber))
            return false;
        return true;
    }

}

重载构造器,比较复杂

这种确实麻烦点,可能有多种情况,为了外部构造的方便,会考虑一些默认情况。
但是我不希望出现null,所以比如集合,会new一下。
这种写法另起炉灶(其实可以考虑用this(),调用已有构造器)

import java.io.Serializable;
import java.util.*;

/**
 * 疾病类型类
 * 这是疾病树的结点
 */
public class DiseaseType implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 疾病ID
     */
    private Integer diseaseId;

    /**
     * 疾病名称
     */
    private String diseaseName;

    /**
     * 疾病上一级分类
     */
    private DiseaseType parentDiseaseName;

    /**
     * 疾病下属子分类集合
     */
    private Map<String, DiseaseType> subIllnessesMap;

    /**
     * 下属病人的集合
     */
    private List<PatientInfo> patientSet;

    public DiseaseType(Integer diseaseId, String diseaseName) {
        this.diseaseId = diseaseId;
        this.diseaseName = diseaseName;
        this.parentDiseaseName = null;
        this.subIllnessesMap = new HashMap<>();
        this.patientSet = new ArrayList<>();
    }

    public DiseaseType(Integer diseaseId, String diseaseName, DiseaseType parentDiseaseName,
                       Map<String, DiseaseType> subIllnessesMap) {
        this.diseaseId = diseaseId;
        this.diseaseName = diseaseName;
        this.parentDiseaseName = parentDiseaseName;
        this.subIllnessesMap = subIllnessesMap;
        this.patientSet = new ArrayList<>();
    }

    public DiseaseType(Integer diseaseId, String diseaseName, DiseaseType parentDiseaseName,
                       Map<String, DiseaseType> subIllnessesMap, List<PatientInfo> patientSet) {
        this.diseaseId = diseaseId;
        this.diseaseName = diseaseName;
        this.parentDiseaseName = parentDiseaseName;
        this.subIllnessesMap = subIllnessesMap;
        this.patientSet = patientSet;
    }

    public String getDiseaseName() {
        return diseaseName;
    }

    public void setDiseaseName(String diseaseName) {
        this.diseaseName = diseaseName;
    }

    public Integer getDiseaseId() {
        return diseaseId;
    }

    public void setDiseaseId(Integer diseaseId) {
        this.diseaseId = diseaseId;
    }

    public DiseaseType getParentDiseaseName() {
        return parentDiseaseName;
    }

    public void setParentDiseaseName(DiseaseType parentDiseaseName) {
        this.parentDiseaseName = parentDiseaseName;
    }

    public Map<String, DiseaseType> getSubIllnessesMap() {
        return subIllnessesMap;
    }

    public void setSubIllnessesMap(Map<String, DiseaseType> subIllnessesMap) {
        this.subIllnessesMap = subIllnessesMap;
    }

    public List<PatientInfo> getPatientSet() {
        return patientSet;
    }

    public void setPatientSet(List<PatientInfo> patientSet) {
        this.patientSet = patientSet;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DiseaseType that = (DiseaseType) o;
        return diseaseName.equals(that.diseaseName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(diseaseName);
    }

    @Override
    public String toString() {
        return diseaseName;
    }

}

感想

有时间的话,这个构造器诶,还是要好好设计啊……

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!