代码之道 - change or not change

代码之道 - change or not change

1. 前言

谈论代码之道可能有些言过其实,我更倾向于将其视为一种交流与分享的机会,以便我们能够共同学习并取得进步,今天我主要从变与不变的角度来和大家分享一下我写代码的一些心得

2. 从设计模式说起

设计模式大家可谓是久闻大名,那到底设计模式解决了什么样的问题呢?

  • 拿一个装饰器模式看看
js 复制代码
// 展示接口
public interface Showable { 
    public void show();
}

public class Girl implements Showable { 

    @Override
    public void show() { 
        System.out.print("女生的脸"); 
    }
    
}

public class Decorator implements Showable{ 

    //被装饰的展示者
    Showable showable;
    
    public Decorator(Showable showable) {
        //构造时注入被装饰者 
        this.showable = showable; 
    } 
    @Override 
    public void show() {
        System.out.print("磨皮");
        //化妆品粉饰开始 
        showable.show();
        //被装饰者的原生展示方法 
        System.out.print("美颜");
        //粉饰结束 
    }
}

public class Client { 
    public static void main(String[] args) { 
        //用装饰器包裹女孩后再展示 
        new Decorator(new Girl()).show(); 
        //运行结果:粉饰【女生的脸】 
   } 
}

可以看到装饰器模式的本质其实就是在不改变原来的代码上,为方法加上新的功能。

但是为什么需要这样呢?你可能会说我在原来的代码上增加两行代码不好吗?

js 复制代码
public class Girl implements Showable { 

    @Override
    public void show() { 
        System.out.print("磨皮");
        System.out.print("女生的脸"); 
        System.out.print("美颜");
    }
    
}

但是这样这个方法就被限定在磨皮美颜 上面了,如果这个女孩在星期一想 磨皮美颜,在星期二想祛痘遮瑕 那就又需要新写一个Girl类了。

也就是最本质是要清楚 女生的脸 一般情况下是 不变的磨皮美颜这些东西是变化的,所以核心是抽象出变化和不变的东西。

我们常常使用的 AOP 其实也可以看作是一种装饰器,只不过由 AOP 实现的更加强大,可以通过注解的方式批量为方法增强功能。

  • 再看看设计模式中的工厂吧
js 复制代码
public abstract class Entity {
    
    //敌人的坐标
    protected int x;
    protected int y;
    
    //初始化坐标
    public Enemy(int x,int y)  {
        this.x = x;
        this.y = Y;
    }
    //抽象方法,在地图上绘制
    public abstract void show();
}

// 飞机类
public class Air extends Entity {

    public Air(int x,int y){
        super(x,y);//调用父类构造方法初始化坐标
    }
    
    @Override
    public void show(){
        System.out.println("绘制飞机于上层图层,出现坐标:"+ x + "," + y);
        System.out.println("飞机出来了");
    }
}


// 车辆
public class Car extends Entity {

    public Tank(int x,int y){
        super(x,y);//调用父类构造方法初始化坐标
    }
    
    @Override
    public void show(){
        System.out.println("绘制汽车于下层图层,出现坐标:"+x + "," + y);
        System.out.println("汽车向玩家出来了");
    }
}

其实也是一样的道理,工厂其实就是抽离了对象不变的本质 实体都有 x y 坐标,并且都会在地图上绘制

所以设计模式其实没有帮你解决任何问题,它是对一类相似问题的抽象的总结,当你看到同样的问题时,你自然就知道选用那种设计模式来让你的代码变得更加简单。

  • 再来看一个更简单的例子
js 复制代码
public class MultiplicationTable { 
    public static void main(String[] args) { 
        System.out.println("1*1=1"); 
        System.out.println("1*2=2\t2*2=4"); 
        System.out.println("1*3=3\t2*3=6\t3*3=9");
        // ... 省略
    }
}

public class MultiplicationTable {
    public static void main(String[] args) { 
        for (int i = 1; i <= 9; i++) { 
            for (int j = 1; j <= i; j++) { 
                System.out.print(j + "*" + i + "=" + (i * j) + "\t"); 
            } 
        }
    } 
}
 

程序界常流传的一个笑话就是,老师让学生写代码输出99乘法表,结果学生直接用手写的方法输出了出来。

这其实就是初学者无法对问题进行更本质的抽象,找到事物中变与不变的部分,所以才造成了这种啼笑皆非的情况。

评价一个代码的好坏,其中的一个方面我想就是有没有对事物或者问题有更本质的思考,提炼出了事物和问题之间不变的共性

3. 那么写代码更核心问题到底是什么

我觉得写好代码有时就和解数学题一样, 都是需要抽象出事物的变和不变的部分,但是最核心的问题其实还是没有对事物抽象的能力,找到一个事物和问题之间的共性其实是很难的。

你可能需要各方面知识都需要有涉猎,就像如果不知道方程,可能就只能使用穷举的方式来解决鸡兔同笼的问题了。

我想很多时候我们写代码时都忽略了需要仔细思考问题本身的共性,而不是直接去解决问题。用蛮力来解决问题很多时候可能只能是事倍功半。

提取出问题和事物的共性,寻求一个问题的最优解,避免重复的体力劳动,可能会让日常的工作变得更加轻松。

相关推荐
2401_85439108几秒前
高效开发:SpringBoot网上租赁系统实现细节
java·spring boot·后端
Cikiss9 分钟前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
Cikiss11 分钟前
微服务实战——平台属性
java·数据库·后端·微服务
OEC小胖胖24 分钟前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
2401_857617621 小时前
SpringBoot校园资料平台:开发与部署指南
java·spring boot·后端
计算机学姐1 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
Yvemil72 小时前
MQ 架构设计原理与消息中间件详解(二)
开发语言·后端·ruby
2401_854391082 小时前
Spring Boot大学生就业招聘系统的开发与部署
java·spring boot·后端
虽千万人 吾往矣2 小时前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
这孩子叫逆3 小时前
Spring Boot项目的创建与使用
java·spring boot·后端