全栈之路-杂篇-探究Java代码

  刚听了七月老师一个讲解Java的视频,忍不住笑了,为什么我们写使用Java语言进行开发,你写的那种烂大街的Java代码,不配称作一个Java程序员,路边随便一个人,你给他讲解了Java的语法,他也能完成这个最基本的demo的代码的开发,到底是什么样的代码,如何才能写出一个程序员该写出的优秀的代码,你作为一个程序员,连程序员思维都没有,你还好意思在占着程序员开发的宝贵位置上,哈哈哈

一、烂大街的代码

  说实话,我平时就是这么写代码的啊,遭到鄙视了,找到自己的不足,并且加以改进,是最让人开心的一件事了,只想活出一个人本来就该有样子,只想写出代码本来就该是那样的代码,继续前行(这里是拿英雄联盟LOL这款游戏举例子的)

看一下烂大街的代码:

1、皎月女神黛安娜

 1 public class Diana {
 2     public void q() {
 3         System.out.println("Diana Q");
 4     }
 5 
 6     public void w() {
 7         System.out.println("Diana W");
 8     }
 9 
10     public void e() {
11         System.out.println("Diana E");
12     }
13 
14     public void r() {
15         System.out.println("Diana R");
16     }
17 }

2、刀锋意志艾瑞莉娅

 1 public class Irelia {
 2     public void q() {
 3         System.out.println("Irelia Q");
 4     }
 5 
 6     public void w() {
 7         System.out.println("Irelia W");
 8     }
 9 
10     public void e() {
11         System.out.println("Irelia E");
12     }
13 
14     public void r() {
15         System.out.println("Irelia R");
16     }
17 }

3、青钢影卡密尔

 1 public class Camille {
 2     public void q() {
 3         System.out.println("Camille Q");
 4     }
 5 
 6     public void w() {
 7         System.out.println("Camille W");
 8     }
 9 
10     public void e() {
11         System.out.println("Camille E");
12     }
13 
14     public void r() {
15         System.out.println("Camille R");
16     }
17 }

4、测试代码

 1 public class Main {
 2     public static void main(String[] args) {
 3         String name = Main.getPlayerInput();
 4         switch (name) {
 5             case "Diana":
 6                 Diana diana = new Diana();
 7                 diana.r();
 8                 break;
 9             case "Irelia":
10                 Irelia irelia = new Irelia();
11                 irelia.r();
12                 break;
13             case "Camille":
14                 Camille camille = new Camille();
15                 camille.r();
16                 break;
17         }
18     }
19 
20     private static String getPlayerInput() {
21         System.out.println("Enter a hero's name");
22         Scanner scanner = new Scanner(System.in);
23         String name = scanner.nextLine();
24         return name;
25     }
26 }

重新看了一遍这几段代码,反复确认过,是似曾相识的样子,我确实是在写这样的代码,惭愧,惭愧,并且我还没有认识到这是一种怎么烂的代码,这才是最让人头疼发的地方,改进,重新来过

二、基于接口的优化

   接口的意义在于将方法抽象出来,统一方法的调用,首先优化的是方法的调用问题,用接口统一方法的调用

1、接口的抽象

创建英雄的公共方法的接口,统一方法的调用,接口默认的scope修饰符是public

1 public interface ISkill {
2     void q();
3     void w();
4     void e();
5     void r();
6 }

2、英雄类实现接口

因为是简单的demo的形式,只有三个英雄,但是基本上内部代码是一样的,这里只列举一个英雄(皎月女神黛安娜)的代码,其余都是一样的,实现ISkill接口

 1 public class Diana implements ISkill{
 2     public void q() {
 3         System.out.println("Diana Q");
 4     }
 5 
 6     public void w() {
 7         System.out.println("Diana W");
 8     }
 9 
10     public void e() {
11         System.out.println("Diana E");
12     }
13 
14     public void r() {
15         System.out.println("Diana R");
16     }
17 }

3、测试代码调用

 1 public class Main {
 2 
 3     public static void main(String[] args) throws Exception {
 4         String name = Main.getPlayerInput();
 5         ISkill iSkill;
 6         switch (name) {
 7             case "Diana":
 8                 iSkill = new Diana();
 9                 break;
10             case "Irelia":
11                 iSkill = new Irelia();
12                 break;
13             case "Camille":
14                 iSkill = new Camille();
15                 break;
16             default:
17                 throw new Exception();
18         }
19         iSkill.r();
20     }
21 
22     private static String getPlayerInput() {
23         System.out.println("Enter a hero's name");
24         Scanner scanner = new Scanner(System.onggin);
25         String name = scanner.nextLine();
26         return name;
27     }
28 }

通过测试代码可以看出,其实优化的地方不是很多,只是将接口的实例化,当用户选择不同英雄的时候,分别实例化,还有就是统一了方法的调用,通过这个优化,七月老师总结出了以下两点重要结论:

(1)interface:单纯的interface可以统一方法的调用。但是它不能统一对象的实例化

(2)面向对象:实例化对象和方法的调用(完成业务逻辑)

 三、基于工厂模式的优化

基于工厂模式的优化,主要是将main函数中对象实例化的代码进行抽离,使得main函数达到一种稳定的状态。

1、接口的抽象

上同接口优化的代码

2、英雄类的实现接口

上同接口优化的代码

3、英雄的工厂类

这个才是这次优化的重点,其实就是将之前main函数中的switch,case代码段放到HeroFactory的getHero方法中,但是这样的优化同样是很有必要的,使得main函数的代码趋于稳定,当增加英雄类的时候,我们不需要更改main函数中的任何代码,只要更改getHero方法中的代码即可,但这还不是最终的优化方案,还有第四步的优化

 1 public class HeroFactory {
 2 
 3     public static ISkill getHero(String name) throws Exception {
 4         ISkill iSkill;
 5         switch (name) {
 6             case "Diana":
 7                 iSkill = new Diana();
 8                 break;
 9             case "Irelia":
10                 iSkill = new Irelia();
11                 break;
12             case "Camille":
13                 iSkill = new Camille();
14                 break;
15             default:
16                 throw new Exception();
17         }
18         return iSkill;
19     }
20 }

4、测试代码调用

 1 public class Main{
 2     public static void main(String[] args) throws Exception {
 3         String name = Main.getPlayerInput();
 4         ISkill iSkill = HeroFactory.getHero(name);
 5         iSkill.r();
 6     }
 7     private static String getPlayerInput() {
 8         System.out.println("Enter a hero's name");
 9         Scanner scanner = new Scanner(System.in);
10         String name = scanner.nextLine();
11         return name;
12     }
13 }

优化的重点结论:

(1)只有一段代码中没有new的出现,才能保持代码的相对稳定,才能逐步实现OCP

(2)上面这段代码只是表象,实质是某一段代码如果要保持稳定,就不应该负责对象的实例化工作

(3)对象的实例化是不可消除的

(4)把对象实例化的过程转移到其他的代码片段中

四、终版-基于反射技术的优化

基于反射技术的优化,最终解决的HeroFactory类中getHero方法中的switch、case代码块的优化,我们利用反射技术根据用户输入的字符串进行对象的创建,从而消除switch、case代码块

1、接口的抽象

上同接口优化的代码

2、英雄类的实现接口

上同接口优化的代码

 3、英雄工厂类

1 public class HeroFactory {
2 
3     public static ISkill getHero(String name) throws Exception {
4         String classStr = "reflect.hero." + name;
5         Class<?> clazz = Class.forName(classStr);
6         Object obj = clazz.newInstance();
7         return (ISkill) obj;
8     }
9 }

注意:

这里有一个需要注意的知识点,当调用Class元类中的forName方法时候,参数一定是包含完成包名的类的路径

4、测试代码的调用

上同工厂模式的优化中的测试代码

五、重点总结

七月老师的重点总结:

(1)interface:单纯的interface可以统一方法的调用。但是它不能统一对象的实例化

(2)面向对象:实例化对象和方法的调用(完成业务逻辑)

(3)只有一段代码中没有new的出现,才能保持代码的相对稳定,才能逐步实现OCP

(4)上面这段代码只是表象,实质是某一段代码如果要保持稳定,就不应该负责对象的实例化工作

(5)对象的实例化是不可消除的

(6)把对象实例化的过程转移到其他的代码片段中

(7)代码中总会存在不稳定,隔离这些不稳定,保证其他代码的稳定性

(8)变化造成了代码的不稳定性

 

 内容出处:七月老师《从Java后端到全栈》视频课程

七月老师课程链接:https://class.imooc.com/sale/javafullstack

posted @ 2020-01-15 15:26  ssc在路上  阅读(300)  评论(0编辑  收藏  举报