java 内部类使用姿势

编程入门 行业动态 更新时间:2024-10-10 08:24:42

java 内<a href=https://www.elefans.com/category/jswz/34/1765347.html style=部类使用姿势"/>

java 内部类使用姿势

大家好,我是入错行的bug猫。(微博:,谢绝转载)

问同事,内(nei)部(bu)类(lei)是什么鬼?
隔壁同事猿一脸懵逼:当然累啊!肿么了?
bug猫:……嗯,没事……我也累……

于是bug猫决定以后放弃问隔壁同事猿了,直接抱住无所不知的度娘大粗腿
(度娘:感谢支持,你还是辞职吧……)


不知道内部类是什么含义的同学请先自行百度~
bug猫只讲怎么高效快速撸代码,原理什么的,bug猫遵循会用就行,以后有兴趣再去了解。

现在用得比较多的框架,有SpringMVC、Spring、Hibernate、Mybatis,比较古老点还有struts2、struts1。
在使用这些框架之前,必须要搞清楚,哪些是多例、哪些是单例。

不知道多例、单例是什么含义的同学请先自行百度~
bug猫知道肯定有不少同学是一脸懵逼。bug猫在面试新同学时,有很多都答不上来。

到这一步,bug猫假设你已经知道单例和多例了。
以SpringMVC为例,SpringMVC默认单例。通过Spring管理的组件,比喻Controller是单例,导致Controller层注入的Service层也是单例!
也就是说如果在Service里面有全局私有属性,会存在线程安全!


好吧,假设你已经知道上述的Service是单例。来一个实际案例分析:

现在有一个特别复杂的业务,比喻订单入库:1个订单主表,n个订单子表,n个日志表。
根据前端传入的参数,有多种判断逻辑,多种业务处理,还有查询系统设置的参数,调上游系统等等。

能力和业务差一点的同学,直接吓趴的那种。

嗯嗯,于是bug猫果断把这块扔给隔壁同事猿做……
最后结果是:Service类中,这个处理业务的方法占了数千行……
没错!就是一个方法数千行代码!

后来业务需求增加,需要从其他入口,也能生成订单。
隔壁同事猿吐血中……
因为那个碉堡了的方法,没法复用……

隔壁同事猿加班最终还是搞定了:
把那个碉堡了的方法,拆成n个方法,每个方法执行特定的功能。
那个碉堡了的方法,变成了只拼装好参数,再调用其他方法的方法。
其他入口生成订单,也是像堆积木一样其他方法拼起来。

问题解决了!隔壁同事猿如是说。
bug猫:隔壁发来贺电!可喜可贺可喜可贺~


哼哼,如果真的完事了,就没这篇博文事了。

老板又来搞事了,需求持续发生变化……

前文说了,Service是单例,不能有全局的私有属性,
隔壁同事猿在n个方法之间,是通过方法上传递的参数耦合在一起:方法dom处理参数ab之后,然后传到方法don中,
伪代码如下:

public void creartOrder(){//创建订单入口...dom(a,b,c);    //模块mdon(a,c,d);    //模块n...
}
private void dom(A a, B b, C c){...exm(a,c, x);   //再调用另外一个方法...
}
private void don(A a, C c, D d){...exn(a,w); //还调用另外一个方法...
}private void exm(A a,C c, X x){...exn(a, null); //继续调用另外一个方法...
}
private void exn(A a, W w){......
}

需求发生变化,导致方法上的参数有增减,进一步影响外层方法上的参数,从而整个生成订单的业务代码全崩了!
隔壁同事猿继续吐血中……

老板:这个需求很简单啊,怎么还要那么久?!
隔壁同事猿持续吐血中……

老板:bug猫,你上!
bug猫吐血中……


现在代码改不动,原因在于方法与方法之间有强耦合:参数类型、参数数量、参数顺序
如果把这些很多方法都用到的参数,提到全局上去,
比喻ac,作为全局属性,那么方法就直接可以使用,无需通过参数传递。
或者再创建一个对象P,把abc等参数作为P的属性,方法与方法直间,通过一个对象耦合在一起。方法增减参数,体现为对象P增加属性。

通过权衡各种利弊,bug猫决定综合上述两个方案:
创建一个OrderFactory类,把abc等参数作为OrderFactory的属性,创建订单的方法,全部转移到OrderFactory类中。也就说,OrderFactory是专门用来创建订单的(单一职能)
OrderFactory类中,abc等参数是全局私有属性,创建订单的方法可以直接使用这些属性,不必像丢锅一样,把这些参数丢来丢去。

在主方法中,new 一个OrderFactory的对象,把abc等参数,赋值给OrderFactory的对应属性。然后再执行OrderFactory对外暴露的execute方法,就直接得到结果。OrderFactory对外而言,体现为一个黑匣子,放入原料abc,执行execute就会产出结果。

看到这里,各位可能会说,“我早就知道要这么玩了!浪费我时间!”

等等!少侠请留步!
写订单、操作数据库还没解决呢!


既然OrderFactory是专门用来创建订单的,如果它把订单对象做好,再扔出来,由主方法来写表,
这就不符合bug猫的美学了。
而且,在创建订单对象同时,还要查询数据库,取各种参数。如果这些也有主方法查询出来后,再传给OrderFactory
就像隔壁同事猿把这个锅甩给我一样,主方法说OrderFactory你怎么这么娇贵?什么东西都要帮你准备好,还要我帮你擦屁股,别乱扔锅!!老朽不干了!

好吧,OrderFactory还要兼具操作数据库的功能,需要dao层,怎么破?

“这还不简单,使用@Autowired或者@Resource自动注入!”
如果这样想,我只能说同学,太甜了!

OrderFactory没有被Spring容器管理,而且是使用new创建的,Spring的注解对它无效!
方法一:你必须把它改造一下,把创建OrderFactory的职能委托给Spring管理(略)
方法二:你可以在主方法中,将dao层作为参数传给OrderFactory(略)
方法三:使用内部类

非静态内部类的特性是,可以无条件使用外部的属性、方法。
就算这些属性、方法,是使用private修饰!

回到主方法所在的Servicedao层是可以使用@Autowired或者@Resource自动注入
=>这些dao层都是Service的私有属性
=>如果Service中有一个非静态内部类,是可以直接使用这些dao层!
=>OrderFactory如果是Service中的非静态内部类,可以直接使用dao层!
于是就可以避免在主方法中,将dao层作为参数一个一个传给OrderFactory

“等等,画风变得太快,我没反应过来!”


我们要优雅解决OrderFactory类中,如何获取数据源,操作数据库。
借用非静态内部类,可以无条件使用外部的属性、方法这个特性,
OrderFactory作为Service的一个非静态内部类!
在主方法中,使用OrderFactory这个内部类时,和使用一个普通的类一样,
直接用 new OrderFactory() 创建。
不过这个类有特殊,在Service类的里面!在创建完毕之后,就可以直接使用外部内的属性、方法。
就像A属于B,现在A存在,那么B一定存在。同样,如果内部类对象存在,那么外部类的对象断言可以存在!

假设外部类叫Out,内部类叫In,那么我们可以使用Out.In in = new Out().new In()来实例化内部类的对象
OrderFactory内部类里面,就可以直接使用,Service中自动注入的dao层了。

再来看一下线程问题,
Service是单例,导致dao层也是单例。
在主方法中,使用 new创建了OrderFactory对象,那么OrderFactory就是多例,多例是容许有全局私有属性(类似struts2的action中,有各种全局属性),没有线程问题。

伪代码:

@Autowired
private Dao dao;public void creartOrder(){//创建订单入口OrderFactory ofy = new OrderFactory(a,b,c);ofy.execute();
}private class OrderFactory{private A a;private B b;private C c;public OrderFactory(A a,B b,C c){this.a = a;this.b = b;this.c = c;}public void execute(){...dom();    //模块mdon(d);    //模块n...}private void dom(){...exm(x);   //再调用另外一个方法...}private void don(D d){...exn(w); //再调用另外一个方法...}private void exm(X x){...exn(null); //继续调用另外一个方法...}private void exn(W w){...dao.insert(a);...}
}


最后总结一下,非静态内部类非常使用于,像Service这种单例中,又需要创建多例对象、又需要共享一些单例资源的场景。


bug猫又一次漂亮地解决完问题~鼓掌~



~THE END~

隔壁同事猿因为被不明人士袭击,重伤请假中…… (づ。◕‿‿◕。)づ





更多推荐

java 内部类使用姿势

本文发布于:2024-02-07 06:09:35,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1754237.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:部类   姿势   java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!