设计模式之美学习-结构型-组合模式(二十四)

应用场景

将一组对象组织(Compose)成树形结构,以表示一种“部分 - 整体”的层次结构

例子1目录描述

描述文件目录

public abstract class FileSystemNode {
  protected String path;

  public FileSystemNode(String path) {
    this.path = path;
  }

  public abstract int countNumOfFiles();
  public abstract long countSizeOfFiles();

  public String getPath() {
    return path;
  }
}

public class File extends FileSystemNode {
  public File(String path) {
    super(path);
  }

  @Override
  public int countNumOfFiles() {
    return 1;
  }

  @Override
  public long countSizeOfFiles() {
    java.io.File file = new java.io.File(path);
    if (!file.exists()) return 0;
    return file.length();
  }
}

public class Directory extends FileSystemNode {
  private List<FileSystemNode> subNodes = new ArrayList<>();

  public Directory(String path) {
    super(path);
  }

  @Override
  public int countNumOfFiles() {
    int numOfFiles = 0;
    for (FileSystemNode fileOrDir : subNodes) {
      numOfFiles += fileOrDir.countNumOfFiles();
    }
    return numOfFiles;
  }

  @Override
  public long countSizeOfFiles() {
    long sizeofFiles = 0;
    for (FileSystemNode fileOrDir : subNodes) {
      sizeofFiles += fileOrDir.countSizeOfFiles();
    }
    return sizeofFiles;
  }

  public void addSubNode(FileSystemNode fileOrDir) {
    subNodes.add(fileOrDir);
  }

  public void removeSubNode(FileSystemNode fileOrDir) {
    int size = subNodes.size();
    int i = 0;
    for (; i < size; ++i) {
      if (subNodes.get(i).getPath().equalsIgnoreCase(fileOrDir.getPath())) {
        break;
      }
    }
    if (i < size) {
      subNodes.remove(i);
    }
  }
}
public class Demo {
  public static void main(String[] args) {
    /**
     * /
     * /wz/
     * /wz/a.txt
     * /wz/b.txt
     * /wz/movies/
     * /wz/movies/c.avi
     * /xzg/
     * /xzg/docs/
     * /xzg/docs/d.txt
     */
    Directory fileSystemTree = new Directory("/");
    Directory node_wz = new Directory("/wz/");
    Directory node_xzg = new Directory("/xzg/");
    fileSystemTree.addSubNode(node_wz);
    fileSystemTree.addSubNode(node_xzg);

    File node_wz_a = new File("/wz/a.txt");
    File node_wz_b = new File("/wz/b.txt");
    Directory node_wz_movies = new Directory("/wz/movies/");
    node_wz.addSubNode(node_wz_a);
    node_wz.addSubNode(node_wz_b);
    node_wz.addSubNode(node_wz_movies);

    File node_wz_movies_c = new File("/wz/movies/c.avi");
    node_wz_movies.addSubNode(node_wz_movies_c);

    Directory node_xzg_docs = new Directory("/xzg/docs/");
    node_xzg.addSubNode(node_xzg_docs);

    File node_xzg_docs_d = new File("/xzg/docs/d.txt");
    node_xzg_docs.addSubNode(node_xzg_docs_d);

    System.out.println("/ files num:" + fileSystemTree.countNumOfFiles());
    System.out.println("/wz/ files num:" + node_wz.countNumOfFiles());
  }
}

比如我们的组织机构树 也可以应用

例子2

需求

实现规则匹配的逻辑 比如>= <=,同时支持 and or 多个条件组合 新增一个条件就增加一个实现类

说明

对于这种需要实现规则匹配的逻辑,可以考虑使用策略模式。策略模式可以将不同的算法封装成不同的策略类,让它们可以相互替换,从而实现不同的行为。在这个问题中,可以将不同的匹配规则封装成不同的策略类,让它们可以相互替换,从而实现不同的匹配行为。

具体实现时,可以定义一个接口,例如 MatchStrategy,其中包含一个 match 方法,用于判断给定的值是否满足当前规则。然后,针对不同的规则,可以实现不同的策略类,例如 GreaterThanStrategy、LessThanStrategy、EqualStrategy 等,它们分别实现 MatchStrategy 接口,并实现自己的 match 方法。

对于多个条件组合的情况,可以使用组合模式来实现。例如,可以定义一个 CompositeMatchStrategy 类,它实现了 MatchStrategy 接口,并包含一个 List<MatchStrategy> 类型的成员变量,用于存储多个子策略。然后,可以定义一个 AndMatchStrategy 类和一个 OrMatchStrategy 类,它们都是 CompositeMatchStrategy 的子类,分别实现了 "and" 和 "or" 运算符的匹配逻辑。

这样,当需要新增一个条件时,只需要新增一个实现了 MatchStrategy 接口的策略类,并将它加入到 CompositeMatchStrategy 中即可。整个匹配逻辑的实现就变得非常灵活和可扩展了。

代码实现

下面是一个简单的示例代码,演示了如何使用策略模式和组合模式实现规则匹配的逻辑。假设我们需要实现一个匹配规则的功能,支持以下几种规则:

  • 大于等于某个值
  • 小于等于某个值
  • 等于某个值
  • 大于某个值
  • 小于某个值

同时,还需要支持 "and" 和 "or" 运算符,让用户可以将多个规则组合起来使用。

首先,我们定义一个 MatchStrategy 接口,用于表示匹配规则:

public interface MatchStrategy {
    boolean match(int value);
}

然后,我们针对不同的规则,实现不同的策略类。例如,对于大于等于某个值的规则,我们可以实现一个 GreaterThanOrEqualStrategy 类:

public class GreaterThanOrEqualStrategy implements MatchStrategy {
    private int threshold;
    
    public GreaterThanOrEqualStrategy(int threshold) {
        this.threshold = threshold;
    }
    
    @Override
    public boolean match(int value) {
        return value >= threshold;
    }
}

类似地,我们还可以实现其他的策略类,例如 LessThanOrEqualStrategyEqualStrategyGreaterThanStrategy 和 LessThanStrategy。这些类都实现了 MatchStrategy 接口,并实现了自己的 match 方法。

接下来,我们需要实现组合模式。我们定义一个 CompositeMatchStrategy 类,用于表示多个匹配规则的组合:

 
public abstract class CompositeMatchStrategy implements MatchStrategy {
    protected List<MatchStrategy> strategies = new ArrayList<>();
    
    public void addStrategy(MatchStrategy strategy) {
        strategies.add(strategy);
    }
}

这个类是一个抽象类,包含一个 List<MatchStrategy> 类型的成员变量 strategies,用于存储多个子策略。它还包含一个 addStrategy 方法,用于向 strategies 中添加子策略。

然后,我们针对 "and" 和 "or" 运算符,分别实现 AndMatchStrategy 和 OrMatchStrategy 类,它们都是 CompositeMatchStrategy 的子类:

public class AndMatchStrategy extends CompositeMatchStrategy {
    @Override
    public boolean match(int value) {
        for (MatchStrategy strategy : strategies) {
            if (!strategy.match(value)) {
                return false;
            }
        }
        return true;
    }
}

public class OrMatchStrategy extends CompositeMatchStrategy {
    @Override
    public boolean match(int value) {
        for (MatchStrategy strategy : strategies) {
            if (strategy.match(value)) {
                return true;
            }
        }
        return false;
    }
}

这两个类都实现了 MatchStrategy 接口,并实现了自己的 match 方法。对于 AndMatchStrategy,它会遍历所有子策略,只有当所有子策略都匹配成功时,才返回 true;对于 OrMatchStrategy,它会遍历所有子策略,只要有一个子策略匹配成功,就返回 true。

最后,我们可以使用这些类来实现规则匹配的逻辑。例如,如果我们需要匹配一个值是否大于等于 10 并且小于等于 20,可以这样写:

 
MatchStrategy strategy = new AndMatchStrategy();
strategy.addStrategy(new GreaterThanOrEqualStrategy(10));
strategy.addStrategy(new LessThanOrEqualStrategy(20));

if (strategy.match(value)) {
    // 匹配成功
}

这样,我们就可以灵活地组合多个规则,并实现复杂的匹配逻辑了。



源码中的使用

tkmapper example查询

https://blog.csdn.net/HiBoyljw/article/details/81330457

 

posted @ 2020-03-26 10:51  意犹未尽  阅读(182)  评论(0编辑  收藏  举报