美文网首页
迪米特法则——合理的封装

迪米特法则——合理的封装

作者: zhanghTK | 来源:发表于2018-07-01 17:29 被阅读0次

    title: 迪米特法则——合理的封装
    date: 2016-10-22 18:55:36
    tags:

    • Java
    • 设计模式
      categories: 设计模式

    背景

    以服务员,客户,钱包为载体,模拟一个付款过程,阐述不恰当的封装行为。

    说明合理封装的一般过程以及不合理封装所表现的一般形式,介绍迪米特法则相关的基本内容,遵循迪米特法则对问题代码进行重构。

    看似没有问题的问题

    先看一个简单代码,分别描述钱包、客户、服务员:

    public class Wallet {
        private double value;
         public double getTotalMoney() {
            return value;
        }
        public void setTotalMoney(double newValue) {
            value = newValue;
        }
        public void addMoney(double deposit) {
            value += deposit;
        }
        public void subtractMoney(double debit) {
            value -= debit;
        }
        // 省略其它字段,方法
    }
    
    public class Customer {
        private Wallet myWallet;
        // 省略其它字段,方法
    }
    
    public class Paperboy {
      private Customer myCustomer;
      public void pay(double payment) {
        Wallet theWallet = myCustomer.getWallet();
        if (theWallet.getTotalMoney() > payment) {
            theWallet.subtractMoney(payment);
        } else {
            //money not enough
        }
      }
    }
    

    一眼看过去,没毛病。几个基本的简单类在Paperboy的pay方法中实现了简单的业务逻辑,但翻译成“人类语言”就有点问题了:

    业务的第一步造作:通过客户获取其钱包。

    等等这样真的好吗?现实生活中仿佛讲不通啊,程序设计中其实违反了迪米特法则。

    听到迪米特法则那一瞬间,我想到的是各种设计模式概念,尴尬的是就是想不起迪米特到底是个啥!

    迪米特法则

    迪米特法则(最小知识法则,强调专注性):

    任何一个对象或者方法,它应该只能调用下列对象:

    • 该对象本身和对象的属性
    • 作为参数传进方法的对象
    • 在方法内创建的对象

    这下好像清晰多了,其实再通俗一点上面的代码就是违反了封装的原则。

    合理的封装分为两步

    1. 分辨职责
      1. 依据:数据与行为应该封装在一起(信息专家模式)
      2. 过程:职责操作哪些数据,数据在哪个(些)类,进而确定职责在哪个类
    2. 判别哪些是实现细节,哪些是可以公开的接口,以保证对细节的合理隐藏

    不良封装造成的结果:Feature Envy(依恋情结)

    不良封装可能的代码样式

    obj1.obj1_fun().obj2_fun();
    

    类似链式的方法调用,但方法返回的是不同对象,这时候的代码很有可能是不良封装,违反迪米特法则了。

    问题的解决

    上面代码良好的封装示例:

    public class Customer {
        private Wallet myWallet;
    
        public void pay(float payment) {
            Wallet theWallet = myWallet;
            if (theWallet.getTotalMoney() > payment) {
                theWallet.subtractMoney(payment);
            } else {
                //money not enough
            }
        }
    }
    
    public class Paperboy {
        private Customer myCustomer;
    
        public void pay(float payment) {
            myCustomer.pay(payment);
        }
    
    }
    

    相关文章

      网友评论

          本文标题:迪米特法则——合理的封装

          本文链接:https://www.haomeiwen.com/subject/csjseftx.html