消除魔法字符串

魔法字符串:指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或数值。风格良好的代码,应该尽量消除魔法字符串,而由含义清晰的变量代替。

以下代码中,'my-token' 就是魔法字符串

// 封装localstory对stoken(对象)的三个操作
// 1.保存   2.获取   3.删除

// 1.保存
export const saveToken = (tokenObj) => {
  localStorage.setItem('my-token', JSON.stringify(tokenObj))
}

// 2.获取
export const getToken = () => {
  return JSON.parse(localStorage.getItem('my-token'))
}

// 3.删除
export const delToken = () => {
  localStorage.removeItem('my-token')
}

可以把 'my-token' 定义为一个常量

// 消除魔法字符串
const TOKEN_NAME = 'my-token'

// 1.保存
export const saveToken = (tokenObj) => {
  localStorage.setItem(TOKEN_NAME, JSON.stringify(tokenObj))
}

// 2.获取
export const getToken = () => {
  return JSON.parse(localStorage.getItem(TOKEN_NAME))
}

// 3.删除
export const delToken = () => {
  localStorage.removeItem(TOKEN_NAME)
}

 

<think>好的,我需要帮助用户优化一个接口的实现类,其中三个方法都使用了同一个实体类的同一个属性进行布尔判断。用户希望优化这段代码。首先,我得理解问题的具体情况。 用户提到三个方法都用到同一个实体类的同一个属性,这意味着可能存在重复代码,每次调用方法时都从实体类中获取该属性,然后进行判断。这样的重复可能会导致代码冗余,维护困难,特别是如果获取属性的逻辑复杂的话。 首先,我应该考虑如何减少重复代码。可能的方法包括将获取属性并生成布尔值的逻辑提取到一个单独的方法中。这样,三个方法可以调用这个公共方法,而不是各自重复相同的代码。这符合DRY原则(Don't Repeat Yourself)。 另外,需要考虑是否可以将这个布尔判断的结果缓存起来,特别是在属性值不变的情况下。如果实体类的属性在对象生命周期内不会改变,可以在初始化时计算一次并存储结果。但如果属性可能变化,缓存可能会导致问题,这时候可能需要其他方法,比如观察者模式来监听属性变化,但这样会增加复杂度,可能不符合用户的优化需求。 接下来,用户可能希望优化性能,减少每次方法调用时重复计算的开销。如果属性值频繁被访问且计算成本高,缓存是有益的。但需要确认属性是否可变,如果可变,缓存需要相应的更新机制。 另外,代码结构方面,可能可以将判断逻辑封装到一个辅助方法中,或者使用策略模式,将不同的判断逻辑分离,但根据用户描述,三个方法都是基于同一个属性的同一判断,可能策略模式并不适用。 还需要考虑线程安全问题。如果多个线程访问同一实例,而属性被修改,是否有同步机制?如果使用缓存,需要确保线程安全,比如使用volatile关键字或原子变量。 可能的优化步骤: 1. 提取公共方法:将获取属性并转换为布尔值的逻辑提取到一个私有方法中。 2. 缓存结果:如果属性不变,在构造方法或初始化时计算并存储布尔值。 3. 使用懒加载:在第一次访问时计算并缓存结果,适用于属性可能变化但不频繁的情况。 4. 依赖注入:将布尔值作为构造参数传入,适用于属性由外部决定的情况。 5. 使用Optional或其他包装类处理可能的null值,增强健壮性。 现在需要权衡这些方法的适用性。用户提到是同一个实体类的同一个属性,所以可能该属性在实例化后不会改变,或者在方法调用期间保持一致。这种情况下,缓存是可行的。如果属性可能改变,每次调用都需要最新值,则不能缓存,只能提取公共方法减少重复代码。 例如,如果实现类在构造时传入实体类实例,可以在构造时获取属性并存储为布尔值,这样三个方法都使用这个预存的布尔值。这适用于属性在实体类实例中不变的情况。 如果属性可能变化,需要在每次调用时获取最新值,那么提取一个私有方法来封装获取和判断逻辑,三个方法调用该方法即可,避免代码重复。 另外,可能还需要考虑实体类属性的访问方式。直接访问字段还是通过getter方法?如果通过getter,可能涉及计算,重复调用可能有性能影响,此时缓存更有必要。 综上,可能的优化方案是提取私有方法,或者根据属性是否可变来决定是否缓存。同时,检查代码是否符合面向对象原则,是否有不必要的重复,以及是否可以通过设计模式来优化结构。 可能还需要考虑是否应该将布尔判断的责任转移到实体类中,比如实体类提供一个方法返回该布尔值,这样实现类只需调用该方法,进一步解耦。 最后,确保优化后的代码保持可读性和可维护性,避免过度设计。根据用户的具体场景,选择最合适的优化方式。</think>--- ### 优化方案:通过**逻辑复用**与**状态集中管理**优化重复判断 若接口实现类的三个方法都依赖同一实体类的同一属性进行布尔判断,可通过以下方式优化代码结构、减少冗余逻辑: --- ### 一、问题分析 **典型代码痛点**: ```java public class MyServiceImpl implements MyInterface { private final Entity entity; // 依赖的实体类 // 三个方法重复获取同一属性并判断 @Override public void methodA() { if (entity.getFlag().equals("ACTIVE")) { // 重复逻辑 // 业务代码 } } @Override public void methodB() { if (entity.getFlag().equals("ACTIVE")) { // 重复逻辑 // 业务代码 } } @Override public void methodC() { if (entity.getFlag().equals("ACTIVE")) { // 重复逻辑 // 业务代码 } } } ``` **问题**: 1. **代码冗余**:相同判断逻辑重复三次 2. **维护风险**:若判断条件变更(如`flag`改为枚举类型),需修改多处 3. **性能浪费**:多次调用`entity.getFlag()`可能触发重复计算(如涉及复杂逻辑) --- ### 二、优化策略(根据场景选择) #### 方案1:提取公共判断方法(基础优化) **适用场景**:属性值可能动态变化,需实时获取最新状态 ```java public class MyServiceImpl implements MyInterface { private final Entity entity; // 提取公共判断方法 private boolean isActive() { return entity.getFlag().equals("ACTIVE"); } @Override public void methodA() { if (isActive()) { // 统一调用 // 业务代码 } } // methodB/methodC 同理... } ``` **优点**: - 消除重复代码,逻辑集中管理 - 修改判断条件时只需改动一处 --- #### 方案2:预计算状态值(推荐用于不变属性) **适用场景**:实体类属性在对象生命周期内不变(如从数据库加载后不再修改) ```java public class MyServiceImpl implements MyInterface { private final Entity entity; private final boolean isActive; // 预存判断结果 // 初始化时计算状态 public MyServiceImpl(Entity entity) { this.entity = entity; this.isActive = entity.getFlag().equals("ACTIVE"); } @Override public void methodA() { if (isActive) { // 直接使用预存值 // 业务代码 } } } ``` **优点**: - 消除重复方法调用开销 - 天然线程安全(`final`确保不可变) --- #### 方案3:状态委托到实体类(面向对象优化) **适用场景**:判断逻辑属于实体类的职责范畴 ```java // 在实体类中封装状态判断 public class Entity { private String flag; public boolean isActive() { // 实体类自身提供判断方法 return "ACTIVE".equals(this.flag); } } // 实现类直接调用 public class MyServiceImpl implements MyInterface { private final Entity entity; @Override public void methodA() { if (entity.isActive()) { // 委托给实体类 // 业务代码 } } } ``` **优点**: - 符合“信息专家”设计模式(数据与行为在一起) - 实现类无需了解判断细节,降低耦合 --- #### 方案4:使用函数式接口(灵活扩展) **适用场景**:需要支持动态判断策略(如测试时替换逻辑) ```java public class MyServiceImpl implements MyInterface { private final Entity entity; private final Predicate<Entity> statusChecker; // 注入判断策略 // 通过构造函数传入策略 public MyServiceImpl(Entity entity, Predicate<Entity> statusChecker) { this.entity = entity; this.statusChecker = statusChecker; } // 默认策略(可选) public MyServiceImpl(Entity entity) { this(entity, e -> e.getFlag().equals("ACTIVE")); } @Override public void methodA() { if (statusChecker.test(entity)) { // 使用策略判断 // 业务代码 } } } ``` **优点**: - 开放扩展:可动态替换判断逻辑(如测试时模拟不同状态) - 符合开闭原则 --- ### 三、优化方案对比表 | 方案 | 适用场景 | 性能 | 可维护性 | 扩展性 | |---------------------|-----------------------------|---------|---------|-------------| | 提取公共方法 | 属性可能变化 | 中 | 高 | 低 | | 预计算状态值 | 属性初始化后不变 | **高** | 高 | 中 | | 状态委托到实体类 | 判断逻辑属于实体职责 | 高 | **最高** | 中 | | 函数式接口策略 | 需要动态切换判断逻辑 | 中 | 高 | **最高** | --- ### 四、增强建议 1. **空值防御**:在判断逻辑中添加`null`检查(如`Optional.ofNullable(entity.getFlag())`) 2. **常量提取**:若`"ACTIVE"`等字符串多次出现,应定义为常量 3. **状态枚举化**:若`flag`为有限状态,建议改为枚举类型 ```java public enum Status { ACTIVE, INACTIVE, PENDING } // 实体类中 private Status status; public boolean isActive() { return status == Status.ACTIVE; } ``` --- ### 最终示例(综合方案2+3) ```java // 实体类 public class Entity { private final Status status; // 使用枚举 public boolean isActive() { return status == Status.ACTIVE; } } // 实现类 public class MyServiceImpl implements MyInterface { private final Entity entity; private final boolean isActive; // 预存结果 public MyServiceImpl(Entity entity) { this.entity = Objects.requireNonNull(entity); this.isActive = entity.isActive(); // 委托实体类判断 } @Override public void methodA() { if (isActive) { // 业务代码 } } // methodB/methodC 同理... } ``` **优化效果**: - ✅ 状态判断逻辑集中在`Entity`类 - ✅ 实现类通过预存值避免重复计算 - ✅ 枚举消除魔法字符串,提升类型安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值