锁定老帖子 主题:尽量少用接口行不行
精华帖 (4) :: 良好帖 (18) :: 新手帖 (0) :: 隐藏帖 (9)
|
|
---|---|
作者 | 正文 |
发表时间:2012-02-02
cataclyzh 写道 碰到一个项目,许多只有一个实例的类也定义了接口,而且这些类还经常要添加方法.结果偷懒的人就在使用到接口的地方直接一个强制装换.
比如函数中传递了IObjectManager接口的,这个接口里面原来只有一个search(String id)方法,后来实现类经常添加方法,修改的人每次改了实现后还要在添加接口定义.结果有些地方的调用就出现了这样的代码: ((IObjectManagerImpl)IObjectManager).search(obj) 问题是这样的代码还运行的挺好的,历经测试,一直延续到最新的版本. 写这样的调用确实不好.但也算事出有因.因为不当的接口使用增加了编码的工作量. 想了想自己使用接口的地方不算多,主要是: 1. 一个接口有多个实现.最常见的是定义事件监听. 2. 需要交给Spring管理的类(一般是DAO层和service层的类). 其他的地方一般先不考虑定义接口.以后有需要了,再加. 思考的好啊! 这种思考是实践之后做出的思考,比其它人只看书本人云亦云未经实践总结就说出来的一套套理论好多了. 写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. 平凡中见真谛,这种思考不应该被投隐藏贴.应积极讨论,百家争鸣. 前面有人提到了JDBC的接口,JDBC的接口用的好啊, 太好了.没人说不好. 因为没有接口JDBC就不能活. SUN公司定义JDBC规范时若不使用接口, 真没有别的方法. 比如说SUN公司1990年制定的JDBC规范(不知具体哪年), 2000年时问世了一个新数据库A公司,实现了JDBC规范,之后大家就可以使用A公司的数据库了. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 比如说Apache 2008年开发了Struts2(不知具体哪年),C人2010年开始使用Struts2,并发现默认配置不能满足业务,所以他针对Struts2的接口做了扩展. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 请注意以上两个事儿共有的3个特点: 1.一个接口有多个实现类(必需是多个,不然说服力不够) 2.有两个角色,SUN公司--A公司,Struts2--C人 3.有时间差,1990年--2000年,2008年--2010年 以上三点太重要了,请先记住. 转眼间到了2012年 ,cataclyzh(楼主)等人 开始开发自己公司的项目,这是一个以增删改查为主的项目,是最帖近用户的项目,并非JDBC,Struts2一类给程序使用的项目. 并定下目标,要写最好的程序:有良好的扩展性,有高质量的代码,有快速跟进用户需求变化的能力,等等..... 项目开发中.... 一个月,两个月...八个月... cataclyzh(楼主)等人遇到的第一难题是:用户需求一变再变 cataclyzh(楼主)等人遇到的第二难题是:交付日期一推再推 经理的脸色越来越难看, 大家开始加班,加班,加班 .修改,修改,修改. cataclyzh(楼主)等人 开始抱怨:实现类经常添加方法和修改,修改的人每次向实现类加了新方法后,还要在接口加添加同样的方法名,甚至项目组里有人偷懒写了楼主说的强制转换代码. 请大家注意这个顺序,是先改实现类,再把代码COPY到接口当中修改接口.完全不是大家预先设想的先定义接口,后写实现类,现在的情形与书中例子说的接口的好处,与其它人的说的接口的好处截然不同,到目前为止cataclyzh(楼主)等人没有体会接口的半点好处.就陷入了深深的思考/深深的思考/深深的思考. 其实这种"快速跟进用户需求变化"的项目,接口是很难抽象出来的(主要是增删改查的业务部分). 当cataclyzh(楼主)等人困惑时,来ITEYE发贴求问,还被投了隐藏贴. ![]() ![]() 还记得前面提到了 "共有的3个特点" 吗? 我们来分析一下,cataclyzh(楼主)所在的项目, 拥有几个? 1.一个接口有多个实现类-- 没有,cataclyzh(楼主)的接口只有一个实现类. 2.有两个角色--没有,永远是cataclyzh(楼主)这一个项目组的三五个人.同一个项目组算一个角色. 3.有时间差--或许有但不明显,基本都是当年或两一二年的项目. 经理的脸色越来越难看,所以眼前的情形是要应付的, 但也要有长远的目光.接口带来的好处是有目共睹的.cataclyzh(楼主)如果想收获接口带来的好处, 还需要先顶过目前的难关,再未来扩展时或许会收获到. 这还是一个"或许",因为但愿你公司的这个最贴近用户的产品还有扩展的机会.jdbc扩展的机会是无限大的不会消失,但你的产品.... 这时候"敏捷"更重要. 最后再重复一次前面说过的话:写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. |
|
返回顶楼 | |
发表时间:2012-02-02
楼上颇能写
|
|
返回顶楼 | |
发表时间:2012-02-02
elf8848 写道 cataclyzh 写道 碰到一个项目,许多只有一个实例的类也定义了接口,而且这些类还经常要添加方法.结果偷懒的人就在使用到接口的地方直接一个强制装换.
比如函数中传递了IObjectManager接口的,这个接口里面原来只有一个search(String id)方法,后来实现类经常添加方法,修改的人每次改了实现后还要在添加接口定义.结果有些地方的调用就出现了这样的代码: ((IObjectManagerImpl)IObjectManager).search(obj) 问题是这样的代码还运行的挺好的,历经测试,一直延续到最新的版本. 写这样的调用确实不好.但也算事出有因.因为不当的接口使用增加了编码的工作量. 想了想自己使用接口的地方不算多,主要是: 1. 一个接口有多个实现.最常见的是定义事件监听. 2. 需要交给Spring管理的类(一般是DAO层和service层的类). 其他的地方一般先不考虑定义接口.以后有需要了,再加. 思考的好啊! 这种思考是实践之后做出的思考,比其它人只看书本人云亦云未经实践总结就说出来的一套套理论好多了. 写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. 平凡中见真谛,这种思考不应该被投隐藏贴.应积极讨论,百家争鸣. 前面有人提到了JDBC的接口,JDBC的接口用的好啊, 太好了.没人说不好. 因为没有接口JDBC就不能活. SUN公司定义JDBC规范时若不使用接口, 真没有别的方法. 比如说SUN公司1990年制定的JDBC规范(不知具体哪年), 2000年时问世了一个新数据库A公司,实现了JDBC规范,之后大家就可以使用A公司的数据库了. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 比如说Apache 2008年开发了Struts2(不知具体哪年),C人2010年开始使用Struts2,并发现默认配置不能满足业务,所以他针对Struts2的接口做了扩展. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 请注意以上两个事儿共有的3个特点: 1.一个接口有多个实现类(必需是多个,不然说服力不够) 2.有两个角色,SUN公司--A公司,Struts2--C人 3.有时间差,1990年--2000年,2008年--2010年 以上三点太重要了,请先记住. 转眼间到了2012年 ,cataclyzh(楼主)等人 开始开发自己公司的项目,这是一个以增删改查为主的项目,是最帖近用户的项目,并非JDBC,Struts2一类给程序使用的项目. 并定下目标,要写最好的程序:有良好的扩展性,有高质量的代码,有快速跟进用户需求变化的能力,等等..... 项目开发中.... 一个月,两个月...八个月... cataclyzh(楼主)等人遇到的第一难题是:用户需求一变再变 cataclyzh(楼主)等人遇到的第二难题是:交付日期一推再推 经理的脸色越来越难看, 大家开始加班,加班,加班 .修改,修改,修改. cataclyzh(楼主)等人 开始抱怨:实现类经常添加方法和修改,修改的人每次向实现类加了新方法后,还要在接口加添加同样的方法名,甚至项目组里有人偷懒写了楼主说的强制转换代码. 请大家注意这个顺序,是先改实现类,再把代码COPY到接口当中修改接口.完全不是大家预先设想的先定义接口,后写实现类,现在的情形与书中例子说的接口的好处,与其它人的说的接口的好处截然不同,到目前为止cataclyzh(楼主)等人没有体会接口的半点好处.就陷入了深深的思考/深深的思考/深深的思考. 其实这种"快速跟进用户需求变化"的项目,接口是很难抽象出来的(主要是增删改查的业务部分). 当cataclyzh(楼主)等人困惑时,来ITEYE发贴求问,还被投了隐藏贴. ![]() ![]() 还记得前面提到了 "共有的3个特点" 吗? 我们来分析一下,cataclyzh(楼主)所在的项目, 拥有几个? 1.一个接口有多个实现类-- 没有,cataclyzh(楼主)的接口只有一个实现类. 2.有两个角色--没有,永远是cataclyzh(楼主)这一个项目组的三五个人.同一个项目组算一个角色. 3.有时间差--或许有但不明显,基本都是当年或两一二年的项目. 经理的脸色越来越难看,所以眼前的情形是要应付的, 但也要有长远的目光.接口带来的好处是有目共睹的.cataclyzh(楼主)如果想收获接口带来的好处, 还需要先顶过目前的难关,再未来扩展时或许会收获到. 这还是一个"或许",因为但愿你公司的这个最贴近用户的产品还有扩展的机会.jdbc扩展的机会是无限大的不会消失,但你的产品.... 这时候"敏捷"更重要. 最后再重复一次前面说过的话:写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. 你可真能写。。。我的想法和你一样,不能简单的用JDK或其他框架的设计思路去对比业务系统,从而评论接口哪里好哪里不好。 框架类项目和业务类项目最大的区别就是需求由谁主导。你写框架,需求和实现很大一部分是由你决定的,所以目标明确,需求稳定,可以抽象出接口,但是业务系统不一样,很多时候需求都在变,叫别人如何能抽象出接口,甚至于可以说,根本没接口,因为需要实现的目标都在变。 我是主张牵涉到业务逻辑的地方,抽象复用这些东西都需要更加谨慎,因为听的最多的就是客户说先按这个做,第二天又说这个需要改改。你抽象了一个看似共通的业务流程,可能第二天就被拆成两个完全不同的逻辑了,这种情况司空见惯了。 |
|
返回顶楼 | |
发表时间:2012-02-02
elf8848 写道 cataclyzh 写道 碰到一个项目,许多只有一个实例的类也定义了接口,而且这些类还经常要添加方法.结果偷懒的人就在使用到接口的地方直接一个强制装换.
比如函数中传递了IObjectManager接口的,这个接口里面原来只有一个search(String id)方法,后来实现类经常添加方法,修改的人每次改了实现后还要在添加接口定义.结果有些地方的调用就出现了这样的代码: ((IObjectManagerImpl)IObjectManager).search(obj) 问题是这样的代码还运行的挺好的,历经测试,一直延续到最新的版本. 写这样的调用确实不好.但也算事出有因.因为不当的接口使用增加了编码的工作量. 想了想自己使用接口的地方不算多,主要是: 1. 一个接口有多个实现.最常见的是定义事件监听. 2. 需要交给Spring管理的类(一般是DAO层和service层的类). 其他的地方一般先不考虑定义接口.以后有需要了,再加. 思考的好啊! 这种思考是实践之后做出的思考,比其它人只看书本人云亦云未经实践总结就说出来的一套套理论好多了. 写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. 平凡中见真谛,这种思考不应该被投隐藏贴.应积极讨论,百家争鸣. 前面有人提到了JDBC的接口,JDBC的接口用的好啊, 太好了.没人说不好. 因为没有接口JDBC就不能活. SUN公司定义JDBC规范时若不使用接口, 真没有别的方法. 比如说SUN公司1990年制定的JDBC规范(不知具体哪年), 2000年时问世了一个新数据库A公司,实现了JDBC规范,之后大家就可以使用A公司的数据库了. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 比如说Apache 2008年开发了Struts2(不知具体哪年),C人2010年开始使用Struts2,并发现默认配置不能满足业务,所以他针对Struts2的接口做了扩展. 所有程序员惊呼----接口万岁,并发誓以后我也充分运用接口. 请注意以上两个事儿共有的3个特点: 1.一个接口有多个实现类(必需是多个,不然说服力不够) 2.有两个角色,SUN公司--A公司,Struts2--C人 3.有时间差,1990年--2000年,2008年--2010年 以上三点太重要了,请先记住. 转眼间到了2012年 ,cataclyzh(楼主)等人 开始开发自己公司的项目,这是一个以增删改查为主的项目,是最帖近用户的项目,并非JDBC,Struts2一类给程序使用的项目. 并定下目标,要写最好的程序:有良好的扩展性,有高质量的代码,有快速跟进用户需求变化的能力,等等..... 项目开发中.... 一个月,两个月...八个月... cataclyzh(楼主)等人遇到的第一难题是:用户需求一变再变 cataclyzh(楼主)等人遇到的第二难题是:交付日期一推再推 经理的脸色越来越难看, 大家开始加班,加班,加班 .修改,修改,修改. cataclyzh(楼主)等人 开始抱怨:实现类经常添加方法和修改,修改的人每次向实现类加了新方法后,还要在接口加添加同样的方法名,甚至项目组里有人偷懒写了楼主说的强制转换代码. 请大家注意这个顺序,是先改实现类,再把代码COPY到接口当中修改接口.完全不是大家预先设想的先定义接口,后写实现类,现在的情形与书中例子说的接口的好处,与其它人的说的接口的好处截然不同,到目前为止cataclyzh(楼主)等人没有体会接口的半点好处.就陷入了深深的思考/深深的思考/深深的思考. 其实这种"快速跟进用户需求变化"的项目,接口是很难抽象出来的(主要是增删改查的业务部分). 当cataclyzh(楼主)等人困惑时,来ITEYE发贴求问,还被投了隐藏贴. ![]() ![]() 还记得前面提到了 "共有的3个特点" 吗? 我们来分析一下,cataclyzh(楼主)所在的项目, 拥有几个? 1.一个接口有多个实现类-- 没有,cataclyzh(楼主)的接口只有一个实现类. 2.有两个角色--没有,永远是cataclyzh(楼主)这一个项目组的三五个人.同一个项目组算一个角色. 3.有时间差--或许有但不明显,基本都是当年或两一二年的项目. 经理的脸色越来越难看,所以眼前的情形是要应付的, 但也要有长远的目光.接口带来的好处是有目共睹的.cataclyzh(楼主)如果想收获接口带来的好处, 还需要先顶过目前的难关,再未来扩展时或许会收获到. 这还是一个"或许",因为但愿你公司的这个最贴近用户的产品还有扩展的机会.jdbc扩展的机会是无限大的不会消失,但你的产品.... 这时候"敏捷"更重要. 最后再重复一次前面说过的话:写与不写接口,这种大家每天都在做的平常平常平常平常事儿,是很难以讨论难以达成共识的,因为人人天天都在做这件事儿,人人都有自己的观点与看法,人人都认为自己的做法是正确的才去行动,没有人认为自己做的是不对的. 同意你的说法,针对你最后一段,再补充下,接口也不是完全无成本的,它的成本就是多一个java类,在调用和被调用者之间多一层关系,也许这层关系很薄,也许相比它带来的收益,成本可以忽略不计。但是,一旦接口完全无法带来收益时(你说的三种情况都没满足),成本已经预先支付(多了一个java类,多了一层关系),那从成本收益上考虑,你就是亏本的。 ![]() |
|
返回顶楼 | |
发表时间:2012-02-02
关于接口的时候,我一般是分为两层来对待:架构层 和 应用层。
架构层: 接口用得很广泛,理论上,一个成熟架构暴露给应用层使用的,都是接口,比如:2001年,你使用如下代码实现发送短信: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 上面代码中,com.chinaunicom.sms.SmsSender是一个接口,在2001年,它的实现类是:GeorgeSmsSenderImpl 到了2012年,com.chinaunicom.sms.SmsSender接口的实现类已经变了三次,现在的实现类是: AndySmsSenderImpl,但是对于应用层的使用者而言,他们发送短信仍然使用: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 应用层使用者的代码完全不用变,这就是接口的好处。 所以,在价构成,要尽量使用接口,理论上,架构层暴露给应用层使用的,应该全是接口。 应用层: 在应用层,接口能不用就不用,代码越简单越好,像楼主举例说的Service、Dao,完全没有必要定义接口,除非你每个Service都有不同的实现类,如果一个Service就是完成一种特定的业务,在可预见的未来也不会有其他实现方式,那样的话,如果你非得给每个Service定义一个接口,只是在自找麻烦。 在我的系统中,每个Service只继承一个通用的基础父类,不用实现任何接口; 对于DAO,则使用如下方式使用DAO来完成数据库访问: HelloWorld bean = dao.getOne(HelloWorld.class,SqlParam.add("id",100)); 至于dao这个变量是怎么来的,应用层使用者完全不用关心,只管放心在Service类或者控制器中,甚至在jsp中使用这个变量即可,更不用费劲地去定义什么Dao接口,写什么Dao实现类。 所以,在应用层,使用者写得代码越少越好,代码越简单越好,接口能不用就不用。 |
|
返回顶楼 | |
发表时间:2012-02-02
int08h 写道 实现类1个,单元测试里Mock类1个
以上,常见的接口作用,所以还是得接口 单元测试也可以MOCK实体例,并不一定MOCK接口 |
|
返回顶楼 | |
发表时间:2012-02-02
george_space 写道 关于接口的时候,我一般是分为两层来对待:架构层 和 应用层。
架构层: 接口用得很广泛,理论上,一个成熟架构暴露给应用层使用的,都是接口,比如:2001年,你使用如下代码实现发送短信: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 上面代码中,com.chinaunicom.sms.SmsSender是一个接口,在2001年,它的实现类是:GeorgeSmsSenderImpl 到了2012年,com.chinaunicom.sms.SmsSender接口的实现类已经变了三次,现在的实现类是: AndySmsSenderImpl,但是对于应用层的使用者而言,他们发送短信仍然使用: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 应用层使用者的代码完全不用变,这就是接口的好处。 所以,在价构成,要尽量使用接口,理论上,架构层暴露给应用层使用的,应该全是接口。 应用层: 在应用层,接口能不用就不用,代码越简单越好,像楼主举例说的Service、Dao,完全没有必要定义接口,除非你每个Service都有不同的实现类,如果一个Service就是完成一种特定的业务,在可预见的未来也不会有其他实现方式,那样的话,如果你非得给每个Service定义一个接口,只是在自找麻烦。 在我的系统中,每个Service只继承一个通用的基础父类,不用实现任何接口; 对于DAO,则使用如下方式使用DAO来完成数据库访问: HelloWorld bean = dao.getOne(HelloWorld.class,SqlParam.add("id",100)); 至于dao这个变量是怎么来的,应用层使用者完全不用关心,只管放心在Service类或者控制器中,甚至在jsp中使用这个变量即可,更不用费劲地去定义什么Dao接口,写什么Dao实现类。 所以,在应用层,使用者写得代码越少越好,代码越简单越好,接口能不用就不用。 应用层使用接口需谨慎有个更重要的理由,就是最开始可能两个业务有类似的地方,于是抽象成了接口,其实随着开发的深入,客户需求的明确和改变,这两个业务原本相似的地方最终很可能变得完全不一样。 |
|
返回顶楼 | |
发表时间:2012-02-02
george_space 写道 关于接口的时候,我一般是分为两层来对待:架构层 和 应用层。
架构层: 接口用得很广泛,理论上,一个成熟架构暴露给应用层使用的,都是接口,比如:2001年,你使用如下代码实现发送短信: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 上面代码中,com.chinaunicom.sms.SmsSender是一个接口,在2001年,它的实现类是:GeorgeSmsSenderImpl 到了2012年,com.chinaunicom.sms.SmsSender接口的实现类已经变了三次,现在的实现类是: AndySmsSenderImpl,但是对于应用层的使用者而言,他们发送短信仍然使用: com.chinaunicom.sms.SmsSender sender = SenderFactory.getDefaultSender(); Result result = sender.send("13999999999","Just a test."); 应用层使用者的代码完全不用变,这就是接口的好处。 所以,在价构成,要尽量使用接口,理论上,架构层暴露给应用层使用的,应该全是接口。 应用层: 在应用层,接口能不用就不用,代码越简单越好,像楼主举例说的Service、Dao,完全没有必要定义接口,除非你每个Service都有不同的实现类,如果一个Service就是完成一种特定的业务,在可预见的未来也不会有其他实现方式,那样的话,如果你非得给每个Service定义一个接口,只是在自找麻烦。 在我的系统中,每个Service只继承一个通用的基础父类,不用实现任何接口; 对于DAO,则使用如下方式使用DAO来完成数据库访问: HelloWorld bean = dao.getOne(HelloWorld.class,SqlParam.add("id",100)); 至于dao这个变量是怎么来的,应用层使用者完全不用关心,只管放心在Service类或者控制器中,甚至在jsp中使用这个变量即可,更不用费劲地去定义什么Dao接口,写什么Dao实现类。 所以,在应用层,使用者写得代码越少越好,代码越简单越好,接口能不用就不用。 顶起楼主。。 目前遇到好多项目中确实清一色的接口调用,其实在分析好架构与应用层后,确实可以不用定义这么多接口。实现类对接口中方法的重载也就是多态的表现。而意义明确的行为,还是不要抽象出接口。日后有需要再添加。 HelloWorld bean = dao.getOne(HelloWorld.class,SqlParam.add("id",100)); TOPLINK 经常用这个 |
|
返回顶楼 | |
发表时间:2012-02-02
像楼主的只有一个实例的例子,我觉得这种情况下是不需要定义成接口的,如果是直接在代码中调用那么定义成静态类或单态类,如果是通过spring等实例化也不需要定义成接口。
那么接口在什么时候定义呢? 接口只有在将来在其他地方有交互且有多种交互方法(具体实现)可选的时候才需要定义,接口定义的永远是行为(交互方法),对于具体的已知的的就不需要定义成接口。
是否要定义接口有一个简单的判断方法,如果在设计时出现了抽象事物(只有类别的名称而没有具体所指的名称)那么就要考虑定义成抽象类或接口,如果只关心行为那么就定义成接口。
比如有一个需求是‘打开电器的开关’,这里电器是抽象事物(指任意电器不是具体的那个电器),关心的是打开开关这个行为,那么要定义成接口,如果是打开那个电视(具体)的开关,就是要定义成类了,如果是‘打开电视的开关’那么就可能要定义成抽象类了,因为电视都有大量共同的属性,而所有的电器就很难找出共同的属性。
看到前面有人说不要学JDK那样定接口,我是不赞同的,JDK中的接口没有像楼主的例子中那样滥用,JDK中不需要接口的地方都没有用到接口啊。 |
|
返回顶楼 | |
发表时间:2012-02-02
我也说一下我的观点,我自己实现时总是尽量先不用接口,怎么快怎么来,只有发现需要抽象了,再写抽象类或接口,仅代表个人意见哈
|
|
返回顶楼 | |