table of Contents
Foreword
In our normal development process, due to time constraints the project, code can be used like, tend to ignore the quality of the code. Some even copied and pasted over, do not collate specification. Often leads to late project difficult to maintain, let alone follow-up to people to take over the project. So, ah, we have to write elegant code, allowing you and me, not Miya?
I share some common coding in the development of the following 小建议
, if wrong, we welcome the exchange of learning together.
Wei statement
Wei statement is to complex conditional expressions into multiple conditional expressions. For example a plurality of if-elseif-else
nested, can be split into a plurality if
. The code below
Code:
-------------------- before --------------------
public void today() {
if (isWeekend()) {
if (isFee()) {
System.out.println("study Android");
} else {
System.out.println("play a game");
}
} else {
System.out.println("go to work");
}
}
-------------------- after (建议) --------------------
public void today() {
// 提前过滤掉`特殊情况`
if (!isWeekend()) {
System.out.println("go to work");
return; // 提前return
}
//提前过滤掉`特殊情况`
if (isFee()) {
System.out.println("study Android");
return; // 提前return
}
// 更关注于 `核心业务`代码实现。
System.out.println("play a game");
}
Filter out ahead of
特殊
the situation, we are more concerned about核心
business logic
Small function
We normally developed, you should write 小而美
a function to avoid 函数过长
. General function best in 15 lines or less ( 建议
) We look at the code below:
-------------------- before --------------------
if (age > 0 && age < 18){
System.out.println("小孩子");
}
if (number.length() == 11){
System.out.println("符合手机号");
}
-------------------- after (建议) --------------------
private static boolean isChild(int age) {
return age > 0 && age < 18;
}
private static boolean isPhoneNumber(String number) {
return number.length() == 11;
}
if (isChild(age)){
System.out.println("小孩子");
}
if (isPhoneNumber(number)){
System.out.println("符合手机号");
}
Analyzing the sentence extracted into one
小函数
, so that the code more clear.
Demeter
concept:
Demeter (Law of Demeter) also called the principle of least knowledge (Least Knowledge Principle abbreviation LKP), that is to say an object should do to other objects 可能少
of 了解
. For example, when an object appears in a statement two .
( student.getName().equals("张三")
) is the code bad taste performance, as shown in the following code.
Code:
-------------------- before --------------------
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static void main(String[] args) {
Student student = new Student("张三");
// 注意看这里,
// 这里获取 student的name属性,在根据name属性进行判断
if (StringUtils.isNotBlank(student.getName()) && student.getName().equals("张三")) {
System.out.println("我的好朋友是 " + student.getName());
}
}
-------------------- after (建议) --------------------
public class Student {
... 省略name代码
// 新增一个 判断是否是我的好朋友方法
public boolean isGoodFriend(){
return StringUtils.isNotBlank(this.name) && this.name.equals("张三");
}
}
public static void main(String[] args) {
Student student = new Student("张三");
// 根据迪米特法则,把判断逻辑,抽取到 Student 内部,暴露出方法(isGoodFriend)
if (student.isGoodFriend()){
System.out.println("我的好朋友是 " + student.getName());
}
}
IDEA / Android Studio extraction method Shortcuts:
option + command + M
Map extracting objects
We usually development, will be used to map
, but in object-oriented development philosophy, one map
use, they tend to miss Java Bean
. Recommended Java Bean
more intuitive. The following code:
public static void main(String[] args) {
-------------------- before --------------------
Map<String, String> studentMap = new HashMap<>();
studentMap.put("张三", "男");
studentMap.put("小红", "女");
studentMap.put("李四", "男");
studentMap.forEach((name, sex) -> {
System.out.println(name + " : " + sex);
});
-------------------- after (建议) --------------------
List<Student> students = new ArrayList<>();
students.add(new Student("张三", "男"));
students.add(new Student("小红", "女"));
students.add(new Student("李四", "男"));
for (Student student : students) {
System.out.println(student.getName() + ":" + student.getSex());
}
}
I write this point in time, we have concerns. There must be a small partner out of it, map
and bean
not the same? Use map
also eliminates the need to think about how I named Class
it. But from the code specification, this type of code design is not more in line with Java 面向对象
the idea of it?
Stream
Java 8 API adds a new abstraction called stream Stream
that allows you to process the data in a declarative way. Making it more elegant code to call - direct look at the code:
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("张三", "男"));
students.add(new Student("李四", "男"));
students.add(new Student("小红", "女"));
students.add(new Student("小花", "女"));
students.add(new Student("小红", "女"));
-------------------- before --------------------
//统计男生个数
//传统的 for each 循环遍历
long boyCount = 0;
for (Student student : students) {
if (student.isBoy()) {
boyCount++;
}
}
System.out.println("男生个数 = " + boyCount);
-------------------- after (建议) --------------------
//统计男生个数
//stream 流遍历
long count = students.stream()
.filter(Student::isBoy) // 等同于.filter(student -> student.isBoy())
.count();
System.out.println("男生个数 = " + boyCount);
}
Compared with the traditional For
cycle, but we recommend using stream
traversal. stream
Chain call flow, show many operations, such as sorted
, map
, collect
and other operators, unnecessary may be omitted if-else
, count
and other decision logic.
Polymorphism
One of the three characteristics of the Java, 多态
, I believe we are not unfamiliar, it is to take advantage of multi-state behavior of different types depending on the subject. We often write switch
the time statement, if the switch to multi-state, each branch can be extracted to overwrite function within a subclass, which is more flexible.
We have such a need to write a simple calculator method, we first look at a snippet of code:
-------------------- before --------------------
public static int getResult(int numberA, int numberB, String operate) {
int result = 0;
switch (operate) {
case "+":
result = numberA + numberB;
break;
case "-":
result = numberA - numberB;
break;
case "*":
result = numberA * numberB;
break;
case "/":
result = numberA / numberB;
break;
}
return result;
}
-------------------- after (建议) --------------------
abstract class Operate {
abstract int compute(int numberA, int numberB);
}
class AddOperate extends Operate {
@Override
int compute(int numberA, int numberB) {
// TODO 在这里处理相关逻辑
return numberA + numberB;
}
}
... SubOperate, MulOperate, DivOperate 也和 AddOperate一样这里就不一一贴出
public static int getResult(int numberA, int numberB, String operate) {
int result = 0;
switch (operate) {
case "+":
result = new AddOperate().compute(numberA, numberB);
break;
case "-":
result = new SubOperate().compute(numberA, numberB);
break;
case "*":
result = new MulOperate().compute(numberA, numberB);
break;
case "/":
result = new DivOperate().compute(numberA, numberB);
break;
}
return result;
}
A small partner might say, you is not more complicated yet?
Compared to the simple switch
, we can interpret it this way:
- Although an increase in the class, but by the polymorphism, separating out the logic operation corresponding to such code is the degree of coupling is reduced.
- If you want to modify the corresponding
加法
logic, we only need to modify the correspondingAddOperate
class on it. Avoid direct modificationgetResult
method - The code more readable, semantic clearer.
But there will be some problems, if we add a new 平方根
, 平方
and so calculation, you need to modify the switch
inside of logic, add a conditional branch. Here we look at further optimization.
reflection
By way of example above, we can further optimize, by 反射
generating a corresponding Class
, then call compute
method. The following code:
public static <T extends Operate> int getResult(int numberA, int numberB, Class<T> clz) {
int result = 0;
try {
return clz.newInstance().compute(numberA, numberB);
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
return result;
}
}
public static void main(String[] args) {
// 调用的时候直接传递 class 即可
System.out.println(getResult(1, 2, SumOpearte.class));
}
The passed class
parameters, and then generates a corresponding Opearte
processing class, polymorphically contrast, here we are reflective, so that the code coupled greatly reduced, if increased 平方根
, 平方
and so calculated. We only need to add a class
succession Opearte
can, getResult
without any changes.
It should be noted that not all
switch
statements need to replace, in the face of a simpleswitch
statement is unnecessary, avoiding过度设计
the suspect. The following code:
public String getResult(int typeCode) {
String type = "";
switch (typeCode) {
case 0:
type = "加法";
break;
case 1:
type = "减法";
break;
case 2:
type = "乘法";
break;
case 3:
type = "触发";
break;
}
return type;
}
Link: https: //juejin.im/post/5dafbc02e51d4524a0060bdd