刚听了七月老师一个讲解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
原文:https://www.cnblogs.com/ssh-html/p/12189591.html