• dljd_001_通过接口降低代码的耦合度(1)


      在学习jdbc之前我们首先来简单学习一下什么是面向接口编程?面向接口编程是怎么降低程序之间的耦合度的、使用面向接口编程给我们带来了那些好处?
    一、需求

      比如说有这样一个需求、让我们用java程序来简单模拟一个人驾驶(启动和停止)一辆宝马车的。当大部分人看到这个需求之后就会觉得这是不是也太简单了、当然这大部分人设计出来的代码基本是如下的情况:

      1.1绝大部分人会有如下的实现:

      1.1.1设计人类  

    package edu.aeon.driver;
    /**
     * [说明]:人类
     * @author aeon
     */
    public class Person {
        /**
         * 当一个类中以属性的方式引入其它类时、那么这种方式被称为聚合
         */
        private BMW bmw;
        public BMW getBmw() {
            return bmw;
        }
    
        public void setBmw(BMW bmw) {
            this.bmw = bmw;
        }
        /**
         * 驾驶
         */
        public void driver(){
            bmw.run();
            bmw.stop();
        }
    }

      1.1.2设计宝马类

    package edu.aeon.driver;
    /**
     * [说明]:宝马类
     * @author aeon
     *
     */
    public class BMW {
        /**
         * 宝马的启动
         */
        public void run(){
            System.out.println("启动宝马、行驶...");
        }
        /**
         * 宝马的停止
         */
        public void stop(){
            System.out.println("停止宝马!");
        }
    }

      1.1.3测试类:

    package edu.aeon.driver;
    /**
     * [说明]:人驾驶宝马测试类
     * @author aeon
     */
    public class TestDriver {
    
        public static void main(String[] args) {
            Person person=new Person();
            BMW bmw=new BMW();
            person.setBmw(bmw);
            person.driver();
        }
    }

     1.1.4测试结果:

      

      我们可以看出来、这个需求是实现了、但是呢这样设计出来的程序是否合理呢?用合成和聚合(关于合成/聚合的含义详见本文档总结部分)关系实现人驾驶宝马是否合理呢?答案是no!

      2.1也有大部分会这么实现

        2.1.1设计人类

    package edu.aeon.driver;
    /**
     * [说明]:人类
     * @author aeon
     */
    public class Person {
        /**
         * 驾驶
         * @param bmw 
         */
        public void driver(BMW bmw){
            bmw.run();
            bmw.stop();
        }
    }

        2.1.2设计宝马类  

    package edu.aeon.driver;
    /**
     * [说明]:宝马类
     * @author aeon
     *
     */
    public class BMW {
        /**
         * 宝马的启动
         */
        public void run(){
            System.out.println("启动宝马、行驶...");
        }
        /**
         * 宝马的停止
         */
        public void stop(){
            System.out.println("停止宝马!");
        }
    }

      2.1.3测试类  

    package edu.aeon.driver;
    /**
     * [说明]:人驾驶宝马测试类
     * @author aeon
     */
    public class TestDriver {
    
        public static void main(String[] args) {
            Person person=new Person();
            BMW bmw=new BMW();
            person.driver(bmw);
        }
    }

      2.1.4测试结果

       

      显然我们看出第二种设计方法比较合理、但是这样设计出来的程序人类和宝马类严重的耦合在一起。当需求发生变化时(如:驾驶一辆奔驰/法拉利/大牛/p1)、我们又要去修改源码。那么怎么设计出来程序比较完美呢?请看第三种设计(面向接口设计/编程)。

      3.1极少部分人设计(非常有经验的人会这么设计)

        3.1.1设计人类  

    package edu.aeon.driver;
    /**
     * [说明]:人类
     * @author aeon
     */
    public class Person {
        /**
         * 驾驶
         * @param car 注意此处:面向接口 
         */
        public void driver(Car car){  //注意
            car.run();
            car.stop();
        }
    }

        3.1.2设计一个汽车接口

    package edu.aeon.driver;
    /**
     * 汽车接口
     * @author aeon
     */
    public interface Car {
        void run();
        void stop();
    }

        3.1.3设计宝马类

    package edu.aeon.driver;
    /**
     * [说明]:宝马类
     * @author aeon
     *
     */
    public class BMW implements Car{
        /**
         * 宝马的启动
         */
        public void run(){
            System.out.println("启动宝马、行驶...");
        }
        /**
         * 宝马的停止
         */
        public void stop(){
            System.out.println("停止宝马!");
        }
    }

        3.1.4测试类  

    package edu.aeon.driver;
    /**
     * [说明]:人驾驶宝马测试类
     * @author aeon
     */
    public class TestDriver {
    
        public static void main(String[] args) {
            Person person=new Person();
            Car car=new BMW();
            person.driver(car);
        }
    }

        3.1.5测试结果截图:

          

        

      那么这种情况可以说设计出来的程序完全符合java力荐的面向接口编程、此处也实现了多态、动态绑定、当需求发生变化时(比如我们现在要驾驶一辆法拉利)、只需要写个法拉利类实现Car这个接口并且重写其实现方法即可。如:  

    package edu.aeon.driver;
    /**
     * [说明]:法拉利类
     * @author aeon
     *
     */
    public class Ferrari implements Car {
        /**
         * 法拉利的启动
         */
        @Override
        public void run() {
            System.out.println("启动法拉利、行驶...");
    
        }
        /**
         * 法拉利的停止
         */
        @Override
        public void stop() {
            System.out.println("停止法拉利!");
        }
    
    }

    Person类不用我们做任何的修改(解耦)。可见面向接口编程给我们带来的巨大便利。    

    四、关于合成和聚合:

      1.合成和聚合关系有整体和局部的意义。比如人是一个整体、而这个人的心脏/胃/...是局部、这里的心脏/胃/...的人体器官是人的一部分。图例如下:

        

      人和心就是整体和局部的关系。人和车是吗?不是吧!

    五、总结

      1.合成/聚合有整体和局部的关系。

      2.一个类成为另一个类的方法参数或者返回值、那么这种关系叫做依赖关系。这里显然人依赖于车才能驾驶、如果没有车那驾驶什么?但是程序中一定要依赖接口去实现。不然还是耦合在一起。

      3.以后我们设计到定义变量类型、方法的参数类型及返回值类型一律使用顶层接口方式。

    如有任何疑问可联系邮箱: 给我发邮件、或直接联系QQ:1584875179 || 点返回首页

  • 相关阅读:
    HDU 4825 Xor Sum
    Linux下使用Crontab定时执行脚本
    HDU 4824 Disk Schedule
    Educational Codeforces Round 26 D. Round Subset 动态规划
    POJ 1833 排列
    HDU 1716 全排列
    HDU 1027 全排列
    Educational Codeforces Round 26 A C 之Python
    ACM输入输出之python
    标准C程序设计七---102
  • 原文地址:https://www.cnblogs.com/aeon/p/10061981.html
Copyright © 2020-2023  润新知