代码重构笔记

重构是为了提升可读性、可维护性、可扩展性。当你不能很清晰的理解这段代码,就需要考虑重构,重构让代码变的更简单、清晰。

重构手法:
1.提取子函数
从一个大代码块中提取到子函数。从而使得原本很长的函数拆分为更多细小的函数,方便阅读。提取子函数又使我们给子函数命名,良好的命名又会给函数产生自解释的作用。

2.上移函数到父类
当A类中使用到 a()方法,而B类等多个类中也需要实现此方法,这个时候就可以考虑把它提取到父类中,如果出现各自方法有差异,就复写其方法。

3.下移函数到子类
当多个子类不需要使用到父类中的函数,而父类又强加于子类,这样就造成耦合。这个时候就要新建一个父类,将此函数写入其中,让后让相关的父类去继承该父类。

4.使用乏型去除重复逻辑
1.
public class StringArrayList {
private String[] dataListTs;
public void set(int position, String data) {
dataListTs[position] = data;
}
}
2.
public class IntArrayList {
private int[] dataListTs;
public void set(int position, int data) {
dataListTs[position] = data;
}
}
不使用乏型,每个类中实现方法是相同的, 如 set, 但是类型不同,这样写如果有很多个类就要不断的写,浪费时间,还有很多重复的代
码。
//使用乏型,大大减少代码量和重复使用量
public class SimplenessArrayList {
private T[] dataListTs;
public SimplenessArrayList(int size) {
dataListTs = (T[]) new Object[size];
}
public void set(int position, T data) {
dataListTs[position] = data;
}
}
5.封装固定的调用逻辑
如果有一个函数,每次调用都要调用其多个方法,那我们就可以将其封装起来
Car car = new Car();
car.unlocking(); //开锁
car.start(); //启动
car.speed(); //速度
每次开车都要用到这3个方法,我们可以把它封装起来
public abstract class SmartCar extends Car{
public void autoSpeedup(int speed){
unlocking();
start();
speed();
}
}
public class Car {
public void unlocking(){}
public void start(){}
public void speed(){}
}
SmartCar smartCar = new SmartCar() {
@Override
public void autoSpeedup(int speed) {
super.autoSpeedup(speed);
}
};
}
6.使用对象避免过多参数
当程序越来越复杂时,一些函数的参数可能就多起来。
public class ShareToData {
private String title;
private String content;
private String thumbUrl;
private String targetUrl;
private String creator;
}
一个方法太多的参数, 当调用不需要用到这么多,就要设置null还有就是造成不知道哪个参数代表什么意思,造成困扰,这个问题传对象
就可以解决
private static void shareToMoment(String title, String content, String thumbUrl,
String targetUrl) {
}
传对象,要什么参数直接获取
private static void shareToMoment(ShareToData shareToData) {
}
7.重构支柱 – 转移函数
如果一个类中有太多的行为(方法)或一个类与另一类之间有太多的函数调用,导致高度耦合, 出现这种情况考虑把该方法(函数)
转移到更适合的类中。
将函数从一个类转移到另一个类中伴随的可能就是函数名的修改。为了保证代码可用,可以把原来的函数通过函数调用的形式调用对
应的函数实现同样的功能。
public class Student {
/**
* 判断是否是某个班级
* @param aClass
* @return
*/
public boolean isBelongTo(AClass aClass){
//代码实现
return true;
}
}
public class AClass {
public ArrayList students = new ArrayList<>();
public void add(Student student){
//实现代码
}
}
AClass要调用 isBelongTo , 这样就造成耦合太强,考虑把方法移过AClass
public class AClass {
public ArrayList students = new ArrayList<>();
public void add(Student student){
//实现代码
}
/**
* 判断是否是某个班级
* @param aClass
* @return
*/
public boolean isBelongTo(Student student){ //更改参数使代码可用
//代码实现
return true;
}
}
8.将类型码转换为状态模式
这是典型的将if-else转换为多态来解决问题的手法,但是,不是任何if-else、switch都应该这样做,这需要根据它们的功能来决定。
比如车子的状态 STOP 、START、 DRIVING
public static final int STOP = 0; 类型码转换成状态码以便更好的维护
public class Vehicle {
private int mState;
public static final int STOP = 0;
public static final int START = 1;
public static final int SPEEDUP = 2;
public void start() {
if (mState == STOP) {
}
}
public void stop() {
switch (mState) {
case START:
break;
case STOP:
break;
}
}
}
当你添加一种新的类型以及类型码时,需要找并跟新所有条件式,如果使用多态,用户只需建立一个新的子类型,并在其中实现相应
的函数,然后在合适的时机构建并且注入该对象即可。用户不需要了解这个子类,这就大大降低了系统各部分之间的相依程度,使系统升级更加容易。

1.抽象类
public abstract class VehicleState {
public void start() {
}
public void stop() {
}
}
2.汽车
public class Vehicle {
private VehicleState mState = new StopState();
public void start() {
mState.start();
mState = new StartState();
}
public void stop() {
mState.stop();
mState = new StopState();
}
}
3.
public class StartState extends VehicleState{
@Override
public void start() {
//执行开车
}
}
public class StopState extends VehicleState{
@Override
public void stop() {
//汽车停止
}
}
这样有功能就直接加载进来就可以

9.什么也不做的对象 —— NullObject模式
//操作类
public class Config {
private StatisticsAPI mStatisticsAPI;
public void setStatisticsAPI(StatisticsAPI api) {
this.mStatisticsAPI = api;
}
public StatisticsAPI getStatisticsAPI() {
return mStatisticsAPI;
}
}
//接口
public interface StatisticsAPI {
void send(String newMsg);
}
//实例
public class NewApp {
Config config;
public NewApp(Config config){
this.config = config;
}
public void userClick(){
StatisticsAPI statisticsAPI = config.getStatisticsAPI();
if(statisticsAPI != null){ //这样每一次都要做空判断,很麻烦
statisticsAPI.send(“用户点击”);
}
}
}
空处理
*.定义一个空指针类
public class NullStatisticsAPI implements StatisticsAPI{
@Override
public void send(String newMsg) {
System.out.println(“什么也不发出, 避免判空”);
}
}
*.调整Config 类
public class Config {
private StatisticsAPI mStatisticsAPI;
private static final StatisticsAPI sNotNullApi = new NullStatisticsAPI(); //1.新建一个空指针类
public void setStatisticsAPI(StatisticsAPI api) {
this.mStatisticsAPI = api;
}
public StatisticsAPI getStatisticsAPI() {
return mStatisticsAPI == null ? sNotNullApi : mStatisticsAPI; //2.这里做处理
}
}
*.Test测试
public class Test {
public static void main(String[] args) {
config = new Config();
//注释掉setStatisticsAPI,就会收到空指针类
config.setStatisticsAPI(new StatisticsAPI() {
@Override
public void send(String newMsg) {
System.out.println(newMsg);
}
});
userClick();
}
static Config config;
public static void userClick() {
StatisticsAPI statisticsAPI = config.getStatisticsAPI();
statisticsAPI.send(“发送消息”); //发送消息
}
}
10.使类保持“苗条身材” —— 分解“胖”类型
某个类做了多个类要做的事情,称它为“胖类型”, 这违反了单一职责原则,解决的方法就是尽量让每个类符合单一原则,从而保持类
的“苗条身材”。

猜你喜欢

转载自blog.csdn.net/qq_18581651/article/details/72123638