接口的一些疑问

1、Java 开发的 dao 层和 service 层都使用接口,是否是为使用接口而使用接口?

Java 中 dao 层和 service 层都使用接口,是否是为使用接口而使用接口?

个人认为,如果没有搞懂为什么用接口,那么有些人就会逢类就要实现接口……在一些业务不复杂的场景下,真的没有必要这样做,但是心里要明白。

前面都说了很多例子和理论了,不过学习就是站在巨人的肩膀上,不断重复,归纳和升华到方法论的过程,再重复一下,引用软件工程文献:

使用接口是为了把调用与实现解耦,带来的好处是可以各干各的,带来的坏处是从一个概念变成了两个概念,增加了系统的复杂度。

衡量一下在具体场景中是弊大于利还是利大于弊,就可以做选择了。

当然,在大部分场景下还要考虑一个因素,就是你会不会写接口。没有良好接口设计能力的人,写出来的接口抽象不合理,等于没写,什么好处都得不到,只有坏处,这种情况下干脆别写。

那怎么衡量你会不会写接口呢,我的经验是,至少见过一次写了接口后得到明确好处的例子。

1.1、什么情况下需要各干各的?

最简单的场景,写接口的是 A,写实现的是 B。当然大多数类似情况没必要真的建一个 interface,然后再让别人去 implement。

另一种情况,调用代码先于实现代码编写。比如 A 开发的是 struts2 这种框架,那 A 先得搞个 Action 接口,让程序先跑起来。

1.2、回答问题

dao 做数据库读写用的。对应上面那几种情况:

1、作为架构师想写两行代码就让小弟加班干活然则自己去泡妹子的话,可能需要写个 interface ,里面几个抽象的 insert、delete 之类的方法;

2、项目在快速原型阶段如果客户满意就掏钱买oracle,如果客户不满意就用免费MySQL的话,你可能需要定义个 dao 接口然后先用内存数据库写点能让原型跑起来的实现,等一切有定论了再说;

3、每个类都有一个dao,每个 dao 都有 crud 方法的话,你可能需要定义一个通用 Dao 接口,然后搞点代码,不用一个个的去写体力代码从此登上人生巅峰。所以dao接口还是有用的。

service 作为业务逻辑的实现,得具体问题具体分析:

不去抠理论的话,什么是 service——就是一段实现了某个逻辑的代码组合。所以 service 是比 dao 更抽象的概念,严格来讲 dao 就是一种 service。只不过在 java 开发中,dao 是个人人都得写的东西,所以都拿出来单说。因此,service 跟 dao 没有本质分别。

1.2.1、从工序上说

写上一层的时候,会用到下一层提供的逻辑,具体表现形式就是各种各样的 service 类和里面的方法。上一层开始的时候,一定会知道下一层会干什么事,比如 “将传入编号对应的人员信息设置为离职”,但下一层的代码不一定已经实现好。所以需要有个接口,让写上层代码的人先能把代码写下去。有各种理由可以支持这种工序的合理性,比如一般来说,上一层的一行代码会对应下一层的好多行代码,那先让写上层代码的人写一遍,解决高端层面的bug,会提高很多效率。

1.2.2、从抽象角度说

不同业务模块之间的共用,不一定是共用某段代码,也可能是共用某段逻辑,这时候就需要抽象一个接口层出来,再通过不同的注入逻辑实现。

比如模块1是登记学生信息,模块2是新闻发布,看上去风马牛不相及。但分析下来如果两个模块都有共同点,顺序都是;

1、验证是否有权限

2、验证输入参数是否合法

3、将输入参数转化为业务数据

4、数据库存取

那就可以写一个 service 接口,里面有上述 5 个方法,再分别写两个 service 实现。具体执行的时候,通过各种注入方法,直接 new 也好,用 spring 注入也好,实现不同的效果。

java 的各种 mvc 框架都提供机制给你干这个事。每个项目或产品,都应该可以用类似的思路抽象出一些东西,如果抽象合理,会很大程度的提高项目架构的合理性。

这些搞定,写个接口然后实现 mock 用于单元测试这种事,信手拈来。

说实话,总结到这里,都是之前的种种的疑问的解答和对概念理解的升华,也是为了复习用,但是说来说去就是那些东西,高内聚,低耦合,开闭原则,单一职责原则,面向接口编程原则,业务和数据分离,工作内容分离,解耦,封装,多态,代码隐藏……其实就是反复这些东西的举例,早已经在十几年前就让前辈和大牛们玩烂的东西……

2、“接口与具体实现分离”,具体实现到底是指什么?

刚开始阅读《Thinging in Java》一书,有如下的说法:

接口与具体实现分离

这里的具体实现如何理解,这里还是要联系到接口的重要使用目的之一:向上转型。

利用接口可以被多个类去实现的特征来分离工作内容,分离不同的业务逻辑而去灵活的插拔不同的但可以替换的实现方法。

例如,有不同的动物,叫声不一样,只需要定义一个”叫声(xxx)“方法,而让牛、羊、青蛙等等去具体实现这个“叫声(xxx)”方法,调用的时候只需要:

动物.叫声(xxx);

就能发出对应动物的叫声了,还要联系接口的一个重要使用目的之二:提供行为的统一的约束,避免实例化,也就是说和具体实现要分离。

在这里再简单重复一些内容:接口往往定义的是一些行为,在设计原则里面有一条“单一职责“的原则,接口的作用只是提供一些方法给你,它不关心你是怎么使用的。就像电脑的 USB 接口,我们不需要关心这个 USB 接口是怎么实现的,我们只需能够使用这个USB接口。

3、封装之后的类,源代码还是能被使用的程序员看到,怎么就说接口起到隐藏的作用?

客户端不等于客户端程序员,可见性也不是针对程序员的,其实很多问题,站在计算机的角度去看就一目了然了。

客户端是指调用它的类或者具体对象,例如私有域不对具体的对象暴露,封装能够保证外部的对象或者实例不能修改它,从而保证了类的安全。

封装的作用不是真的把所有代码实现都让客户端程序员看不到,这个隐藏的目的是让客户端在调用方法等行为时能够按照编写 API 的程序员制定的规则来:一个变量不能让人家随便修改,也不能随便就能获得值,赋值要通过 setter,获得值需 getter 等方法,变量相应的就要通过 private 来隐藏。

举一个形象的例子,形容程序员给用户留了误操作的坑,用来描述因封装不当、没有对类做好隐藏而导致 API 使用问题也是可以的。

假设有一个自行车类,它有两个成员变量——轮子(wheel)和踏板(pedal),它希望客户端能调用『踩踏板』这个方法前进,也能调用『换轮子』这个方法维修自行车,但决不能让用户在『踩踏板』的同时『换轮子』,甚至像图上那样把棍子插轮子的缝隙里,那么就需要把轮子变量设为 private——隐藏起来,不让用户自由获取,得按照你的规则来。

比如骑车的时候就只返回 null,停止的时候就可以返回正常——让用户可以做换轮子之类的工作。

setter 的作用也是类似的,都是为了保证客户端调用时能够遵循 API 设计者的规则,否则调用时就会出现各种不可控的乱象,轻则让调用者骂『这是哪个 SB 设计的 API,代码写起来太难管理了』,重则会出现很多意想不到的 bug,也许实际上的封装应该是对轮子再做进一步的封装,那么就要用内部类的方式。

总之看书的时候对有些想很久也不能明白的东西不用太钻牛角尖,先照着书上说的做,等写了足够的代码,经验多一点了,自然就能理解一些东西为什么要那样做了。

原文地址:https://www.cnblogs.com/kubixuesheng/p/10340267.html

时间: 2024-11-05 21:40:01

接口的一些疑问的相关文章

慢慢人生路,学点Jakarta基础-深入剖析Java的接口和抽象类

在java面向对象编程的,抽象类和接口始终存在有疑问的地方,因为两者太多相似有太多不同,在刚开始学习的时候经常弄的不对,使用情景搞混,今天来总结之前学习Java中接口和抽象类的问题. 抽象类 了解:只声明,未具体实现. abstract void cry(); 抽象方法必须使用关键字abstract进行修饰,如果一旦一个类中包含了abstract方法,那么这个类必须使用abstract进行修饰:因为抽象类中含有未实现的方法,抽象类不能被实例化:抽象类不一定包含抽象方法,也就是说抽象类可以没有抽象

Java核心技术卷一 4. java接口、lambda、内部类和代理

接口 接口概念 接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义. 如果类遵从某个特定接口,那么久履行这项服务. public interface Comparable<T>{ int compareTo(T other); } 任何实现 Comparable 接口的类都需要包含 compareTo 方法,并且这个方法的参数必须是一个 T 对象,返回一个整形数值. 接口的特点: 接口中所有方法自动地属于 public,所以接口的方法不需要提供关键字 public .

读书笔记4: &lt;&lt;Effective C++&gt;&gt;之设计与声明

每一个Item都很经典,都需要去思考揣摩,我在这里将要点抽象出来,便于日后快速回忆:我只是在做文章的"搬运工". Item 18 使接口易于正确使用 1. function接口,class接口,template接口......每一种接口都是客户(调用者)与你的代码互动的手段. 2. 防止可能的客户(调用)错误的另一个方法是:限制类型内什么事可以做什么事不能做:施加限制的一个普通方法就是加上 const. 3. 避免自定义与内置类型不兼容的一个方法是提供行为一致的接口.很少有其他性质比得

接口多继承自接口和接口是否可以继承自一般类的疑问?

接口是常量值和方法定义的集合.接口是一种特殊的抽象类. Java类是单继承的.classB Extends classA java接口可以多继承.Interface3 Extends Interface0, Interface1, interface-- 不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢? 但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口. 注意: 1)一个类如果实现了一个接口,则要实现该接口

Android自学小疑问、小知识点之 监听事件通过接口方式 多次实现监听器

如果点击按钮在实现监听时setOnClickListener(this):实现的是同一接口,那么我们可以通过switch()的方式简单的匹配就不用生成那么多匿名内部类了! 具体实现步骤: 1.初始化第一个点击按钮 imageView = (ImageButton) findViewById(R.id.imageView); 2.实现监听setOnClickListener(this): 3.实现接口方式实现监听 4.初始化第二个点击按钮 imageView2 = (ImageButton) fi

谈谈-Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

C# 接口应用及意义

写在前面:新手入行,读者勉强看看吧,写的不对的欢迎讨论,板砖轻拍! 一.定义 接口描述的是可属于任何类或结构的一组相关功能,所以实现接口的类或结构必须实现接口定义中指定的接口成员. 通常用Interface关键字进行定义. 接口内部只包含方法名,属性等,不含任何访问修饰符. 二.疑问 很多像笔者这样的新手在看到接口的定义及作用后都会产生疑问:接口内部方法只有方法名我们何必去继承这个接口呢?完全可以在应用方法的类里写一个方法调用嘛,何必多此一举呢? 每个继承的类的方法内部代码依然也是不一样,继承时

【转载】COM 组件设计与应用(九)——IDispatch 接口 for VC6.0

原文: http://vckbase.com/index.php/wv/1224.html 一.前言 终于写到了第九回,我也一直期盼着写这回的内容耶,为啥呢?因为自动化(automation)是非常常用.非常有用.非常精彩的一个 COM 功能.由于 WORD.EXCEL 等 OFFICE 软件提供了“宏”的功能,就连我们使用的VC开发环境也提供了“宏”功能,更由于 HTML.ASP.JSP 等都要依靠脚本(Script)的支持,更体现出了自动化接口的重要性. 如果你使用 vc6.0 的开发环境,

IIS8发布WCF接口中遇到的问题总结

环境:系统Win8.1+VS2013+IIS8 在VS13中新建一个WCF服务应用程序,新建之后系统会默认给我们新建一个方法. 我们直接将这个程序发布在IIS之下,或者直接F5运行本来美美的想看到程序运行成功的画面结果系统直接报黄页: 大致的信息就是这样"未能从程序集“System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c5619",哥看到这报错直接懵逼了,这特么是个什么鬼?不管他,直接右