我的BO之数据保护

我的BO
1-我的BO之强类型
2-我的BO之数据保护

数据保护指什么

软件的运行离不开数据,数据一般存在对象中。这种对象在 Java 统称为 POJO,在 C# 则为 POCO。若 POJO 的Property(属性)都是可读写的(publicget/set),没有方法或只有少量的持久化方法,这种称为贫血模型。

贫血模型只存储数据而对数据没有控制,对象内部和外部都能修改。业务逻辑一般写在外部,就算写在内部也因为 Property 可由外界随意修改而控制不住数据。从而这个 POJO 只是存储数据,没有控制数据的能力,也就没有保护数据的能力。一个对象相关的逻辑不能被很好地集中管理,而是分散在各个外部方法中。从而产生了几个不良后果:

贫血模型缺点多

  1. 不同情况下对同份数据的处理有逻辑矛盾,且不易发现。如一处设属性值为-1,另一处却没有考虑值是-1的情况。
  2. 相同的功能写多份,修改时容易改漏。经常复制粘贴的代码后果很可怕。
  3. 软件的质量很差,容易发生改了一个 Bug 产生两个 Bug。难以交付。

BO 如何保护数据

BO 中全部的 Property 对外都是只读的,外部无法直接修改 Property。只有 BO 自己内部才能修改属性,从而保护了数据。外部通过调用 BO 的业务方法修改一个或多个属性,业务方法可对参数和状态进行各种判断,满足条件才修改数据。从而保证任何时候 BO 的数据都是合法的。由于数据只能在内部修改,所以什么值代表什么意思是由 BO 自己决定的,统一决定,而不是由外部分散在各个地方的代码逻辑决定的,所以有效地保证了数据含义的统一性。

虽然关于这个 BO 自己的业务都写到 BO 这个类中了(这里暂无须考虑通过继承写到多个类的情况),起到了集中控制的效果。但内部不同的业务方法也可能有共用的逻辑,这些应该通过重构功能,以达到“一个功能只写一处”的状态。一个大功能会包含若干个小功能,这里的“功能”,是泛指大大小小的任何一个功能。无论是面向对象还是面向过程,都应该努力做到“一个功能只写一处”。这是解决软件灵活性与软件正确性的唯一比较可取的做法。除非把人当作机器,面对之前大量“复制粘贴再改改”的代码需要修改时也能毫不遗漏地全部修改。

BO 的实例化

BO 被定义为任何时刻都是有意义的,所以并不能new一个空对象,然后再赋值,数据必须在new时就送来,所以 BO 需要提供一个全部属性的构造方法。另外为了持久化方便的考虑,也可以接收一个 PO,从 PO 获取各个属性的值。

import com.abc.enumInfo.RepairStatus;
import com.abc.mybatis.model.Repair;
import com.abc.service.db.RepairDB;
import com.abc.util.BoTrackState;

public class RepairBo extends BoBase {
    Repair repair;
    @Autowired
    RepairDB repairDB;

    public RepairBo(Repair repair) {        // 传入PO
        if (repair == null)
            throw ParameterException.missData("repair");
        this.repair = repair;
    }

    public RepairBo(String code, Long depId, String reportUserName, String contactPhone, Date reportTime,
                    String address,  Long createUserId, Date createTime, RepairStatus status) {     // 传入每个属性
        Repair entity = new Repair();
        entity.setCode(code);
        entity.setDepId(depId);
        entity.setReportUserName(reportUserName);
        entity.setContactPhone(contactPhone);
        entity.setReportTime(reportTime);
        entity.setAddress(address);
        entity.setCreateUserId(createUserId);
        entity.setCreateTime(createTime);
        entity.setStatus(status.toString());
        this.repair = entity;
        this.trackState = BoTrackState.Added;
    }

    // region 属性

    public Long getId() {
        return repair.getId();
    }

    protected void setId(Long id) {
        repair.setId(id);
        setTrackUpdate();
    }

    public String getCode() {
        return repair.getCode();
    }

    protected void setCode(String code) {
        repair.setCode(code);
        setTrackUpdate();
    }

    public Long getDepId() {
        return repair.getDepId();
    }

    protected void setDepId(Long depId) {
        repair.setDepId(depId);
        setTrackUpdate();
    }

    public String getReportUserName() {
        return repair.getReportUserName();
    }

    protected void setReportUserName(String reportUserName) {
        repair.setReportUserName(reportUserName);
        setTrackUpdate();
    }

    public String getContactPhone() {
        return repair.getContactPhone();
    }

    protected void setContactPhone(String contactPhone) {
        repair.setContactPhone(contactPhone);
        setTrackUpdate();
    }

    public Date getReportTime() {
        return repair.getReportTime();
    }

    protected void setReportTime(Date reportTime) {
        repair.setReportTime(reportTime);
        setTrackUpdate();
    }

    public String getAddress() {
        return repair.getAddress();
    }

    protected void setAddress(String address) {
        repair.setAddress(address);
        setTrackUpdate();
    }

    public Long getCreateUserId() {
        return repair.getCreateUserId();
    }

    protected void setCreateUserId(Long createUserId) {
        repair.setCreateUserId(createUserId);
        setTrackUpdate();
    }

    public Date getCreateTime() {
        return repair.getCreateTime();
    }

    protected void setCreateTime(Date createTime) {
        repair.setCreateTime(createTime);
        setTrackUpdate();
    }

    public RepairStatus getStatus() {
        String sStatus = repair.getStatus();
        return RepairStatus.valueOf(sStatus);
    }

    protected void setStatus(RepairStatus status) {
        String sStatus = status.toString();
        repair.setStatus(sStatus);
        setTrackUpdate();
    }
    // endregion 属性

    // region 操作

    public void delete() {
        this.setTrackDeleted(); // 方法在base中
        this.save();    // 方法在base中
    }

    // 业务方法: 派单
    public void assignCheck() {
        this.setStatus(RepairStatus.已派单);
        this.save();
    }

    // 业务方法: 勘查
    public void prospecting(String address) {
        this.setAddress(address);
        this.setStatus(RepairStatus.故障属实);
        this.save();
    }

    // endregion 操作

不足之处

没有对构造时的数据进行合法性验证。解决办法可以在构造时检查,若非法则抛异常。也可以私有化构造方法,并提供public static方法,若非法则返回null

感谢

感谢 Rayman(QQ:25625607) 在我为【BO 的属性该全只读,通过方法来修改】还是【可以部分属性可写(public set),并在写时作业务逻辑】举棋不定时给我了肯定的回答。我认为这是整个 BO 的关键所在。

猜你喜欢

转载自www.cnblogs.com/BillySir/p/10807218.html