ARTS是什么? Algorithm:每周至少做一个LeetCode的算法题 Review:阅读并点评至少一篇英文技术文章 Tip:学习至少一个技术技巧,总结和归纳日常工作中遇到的知识点 Share:分享一篇有观点和思考的技术文章

Algorithm

完成leetcode算法第678题。

现在还不会贪心算法和动态规划。所以用栈的方式先实现了一遍,到时候学完其他两种写法再复习这道题。

  1. package com.ohyoung.leetcode.stack;
  2. import java.util.Stack;
  3. /**
  4. * 给定一个只包含三种字符的字符串:(,)和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
  5. *
  6. * 任何左括号 (必须有相应的右括号 )。
  7. * 任何右括号 )必须有相应的左括号 (。
  8. * 左括号 ( 必须在对应的右括号之前 )。
  9. * *可以被视为单个右括号 ),或单个左括号 (,或一个空字符串。
  10. * 一个空字符串也被视为有效字符串。
  11. *
  12. * 示例 1:
  13. *
  14. * 输入: "()"
  15. * 输出: True
  16. * 示例 2:
  17. *
  18. * 输入: "(*)"
  19. * 输出: True
  20. * 示例 3:
  21. *
  22. * 输入: "(*))"
  23. * 输出: True
  24. *
  25. * @author ohYoung
  26. * @date 2021/9/12 10:01
  27. */
  28. public class CheckValidString678 {
  29. private boolean checkValidString(String s) {
  30. // )(是非法的 --> 括号的匹配和顺序有关, 所以stack存储的是每个字符在字符串中的下标用来判断括号的顺序是否合法
  31. Stack<Integer> left = new Stack<>();
  32. Stack<Integer> general = new Stack<>();
  33. for (int i = 0; i < s.length(); i++) {
  34. char c = s.charAt(i);
  35. if (c == '(') {
  36. left.add(i);
  37. } else if (c == '*') {
  38. general.add(i);
  39. } else {
  40. if (!left.isEmpty()) {
  41. left.pop();
  42. } else if (!general.isEmpty()) {
  43. general.pop();
  44. } else {
  45. return false;
  46. }
  47. }
  48. }
  49. // 如果左括号和*都还存在, 将*看作右括号和左括号进行匹配, 同时注意顺序
  50. while (!left.isEmpty() && !general.isEmpty()) {
  51. if (general.pop() < left.pop()) {
  52. return false;
  53. }
  54. }
  55. return left.isEmpty();
  56. }
  57. }

Review

Domain Primitives: what they are and how you can use them to make more secure software
什么是Domain Primitive,怎么利用它使得我们的软件更安全。

  • 用强类型代表带有业务含义的参数,比如用PhoneNumber代替String
  • 校验规则写在对应的强类型对象中,保持单一原则
  • 业务行为封装在对象中,减少胶水代码带来的混乱

    Tip

    orm框架替换后,如何避免大量代码修改的情况?
    我们的代码进入到dao层的时候,通常会用mybatis或JPA等一些框架提供的方法和数据库进行交互。示例代码如下: ```java // JPA的repository层 public interface MdCurrencyRepository extends BaseRepository {

    public MdCurrency findByName(String name); }

// dao层调用 @Autowired private MdCurrencyRepository currencyRepository;

public MdCurrency getByName (String name) { return currencyRepository.findByName(name); }

  1. 如果我们的orm框架没有替换,代码不会有任何问题。但是如果框架由于某种原因需要替换成Mybatis,所有使用到currencyRepository.findByName(name);的代码都需要替换掉,影响范围大。这时候我们可以用**面向接口编程**的方式去解决。首先我们定义一个接口:
  2. ```java
  3. public interface MdCurrencyDao {
  4. public MdCurrency findByName(String name);
  5. }

然后定义实现类:

  1. public class MdCurrencyDaoImpl implements MdCurrencyDao{
  2. @Autowired
  3. private MdCurrencyRepository currencyRepository;
  4. public MdCurrency findByName(String name) {
  5. return currencyRepository.findByName(name);
  6. }
  7. }

客户端调用:

  1. public class MdCurrencyService {
  2. @Autowired
  3. private MdCurrencyDao currencyDao;
  4. public MdCurrency findByName(String name) {
  5. return currencyDao.findByName(name);
  6. }
  7. }

这样就算我们替换了orm框架,我们只需要将MdCurrencyDaoImpl中的jpa替换成mybatis的实现就行,客户端调用的方法一个字都不用改动,影响范围小且可测试性强。

Share

输出文章 - DDD系列(一):Domain Primitive

Finish

预计完成时间:2021.09.06 ~ 2021.09.12
实际完成时间:2021.09.12