设计模式-组合模式

组合模式一个重要的特点就是所有的组合模式都能被解析成一颗树的结构

1. 示例 实现一个计算一个省人口的类

继承 PopulationNode人口节点接口 实现相应的类 . 城市,省, 区 等类

java 复制代码
package club.shengsheng.desigin.combine;

/**
 * 区
 */
public class District implements PopulationNode {

    public final String name;

    public int population;

    public District(String name,int population){
     this.name = name;
     this.population = population;
    }



    @Override
    public int computePopulation() {
        return population;
    }
}
  1. 城市
java 复制代码
package club.shengsheng.desigin.combine;


import java.util.ArrayList;
import java.util.List;

/**
 * 组合设计模式
 * **/
public class City implements PopulationNode {

    private final String name;
    private List<PopulationNode> districts = new ArrayList<>();

    public City(String name) {
        this.name = name;
    }

    public void addDistrict(District district) {
        this.districts.add(district);
    }

    public String getName(){
        return this.name;
    }

    @Override
    public int computePopulation() {
        // 计算城市人口
        return districts.stream().mapToInt(PopulationNode::computePopulation).sum();
    }
}
java 复制代码
package club.shengsheng.desigin.combine;

import java.util.ArrayList;
import java.util.List;

public class Province implements PopulationNode {

    private final String name;

    private List<PopulationNode> cityList = new ArrayList<>();

    public Province(String name) {
        this.name = name;
    }

    public void  addCity(City city) {
        this.cityList.add(city);
    }

    @Override
    public int computePopulation() {
        return cityList.stream().mapToInt(PopulationNode::computePopulation).sum();
    }
}

组合模式的困难之处在于组成这个类

2. 示例 用组合模式实现一个计算器的逻辑

java 复制代码
package club.shengsheng.desigin.combine.compute;

/**
 * 这是计算器表达式的根节点
 */

public interface Expression {

    Integer getValue();

}

中缀表达式转后缀表达式的实现. (核心逻辑)

java 复制代码
 // 中缀表达式转为后缀表达式
    public List<String> toSuffix(){
        // 后缀表达式
        List<String> suffix = new ArrayList<>();
        // 辅助栈
        LinkedList<String> stack = new LinkedList<>();
        // 1 是数字直接入栈
        while (point < infixExpression.length()) {
            char c = infixExpression.charAt(point);
            if(c == '('){
                stack.push(String.valueOf(c));
            }else if(c == ')'){
                // "1+(2+(5*3))"
                while(!stack.isEmpty() && !stack.getLast().equals("(")){
                    // 把辅助栈最后一个元素加入结果中
                     suffix.add(stack.removeLast());
                }
                System.out.println("last: " + stack.getLast());

                stack.removeLast();
            }else if(c == '*' || c == '/'){
                while((!stack.isEmpty()) &&stack.getLast().equals("*") || stack.getLast().equals("/")){
                    suffix.add(stack.removeLast());
                }
                stack.addLast(c+"");
            }else if(c == '+' || c == '-'){
                while(topIsOperator(stack)){
                    suffix.add(stack.removeLast());
                }
                stack.addLast(c+"");
            } else if (Character.isDigit(c)){
                StringBuilder sb = new StringBuilder();
                while(point<infixExpression.length() &&  Character.isDigit(infixExpression.charAt(point))    ){
                   sb.append(infixExpression.charAt(point));
                   point++;
                }
                point --;
                suffix.add(sb.toString());
            }else{
                throw  new IllegalArgumentException("非法字符");
            }
            point ++;
        }

        while(!stack.isEmpty()){
            suffix.add(stack.removeLast());
        }
        return suffix;
    }

完整的表达式解析的类 , 使用栈实现 , 中缀表达式转后缀表达式

java 复制代码
package club.shengsheng.desigin.combine.compute;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * 表达式解析器
 */
public class ExpressionParser {

    // 中缀表达式
    private final String infixExpression;

    private Integer point = 0;

    //中缀表达式转正后缀表达式
    public ExpressionParser(String infixExpression) {
     this.infixExpression = infixExpression;
    }
    // 中缀表达式转为后缀表达式
    public List<String> toSuffix(){
        // 后缀表达式
        List<String> suffix = new ArrayList<>();
        // 辅助栈
        LinkedList<String> stack = new LinkedList<>();
        // 1 是数字直接入栈
        while (point < infixExpression.length()) {
            char c = infixExpression.charAt(point);
            if(c == '('){
                stack.push(String.valueOf(c));
            }else if(c == ')'){
                // "1+(2+(5*3))"
                while(!stack.isEmpty() && !stack.getLast().equals("(")){
                    // 把辅助栈最后一个元素加入结果中
                     suffix.add(stack.removeLast());
                }
                System.out.println("last: " + stack.getLast()); 
                stack.removeLast();
            }else if(c == '*' || c == '/'){
                while((!stack.isEmpty()) &&stack.getLast().equals("*") || stack.getLast().equals("/")){
                    suffix.add(stack.removeLast());
                }
                stack.addLast(c+"");
            }else if(c == '+' || c == '-'){
                while(topIsOperator(stack)){
                    suffix.add(stack.removeLast());
                }
                stack.addLast(c+"");
            } else if (Character.isDigit(c)){
                StringBuilder sb = new StringBuilder();
                while(point<infixExpression.length() &&  Character.isDigit(infixExpression.charAt(point))    ){
                   sb.append(infixExpression.charAt(point));
                   point++;
                }
                point --;
                suffix.add(sb.toString());
            }else{
                throw  new IllegalArgumentException("非法字符");
            }
            point ++;
        }

        while(!stack.isEmpty()){
            suffix.add(stack.removeLast());
        }
        return suffix;
    }

    public Expression parse(){
        List<String> suffix = toSuffix();
        for(String s : suffix){
            System.out.print(s+"  ");
        }
        System.out.println();
         // 
        LinkedList<Expression> stack = new LinkedList<>();
        for (String item : suffix) {
            if(item.equals("+")){
                Expression right = stack.removeLast();
                stack.addLast(new AddExpression(stack.removeLast(),right));
            }else if(item.equals("-")){
                Expression right = stack.removeLast();
                stack.addLast(new SubstractExpression(stack.removeLast(),right));
            }else if(item.equals("*")){
                Expression right = stack.removeLast();
                Expression left = stack.removeLast();
                stack.addLast(new MultiplyExpression(left,right));
            }else if(item.equals("/")){
                Expression right = stack.removeLast();
                stack.addLast(new DevisionExpression(stack.removeLast(),right));
            }else{
                System.out.println("item: "+item);
               Integer value = Integer.parseInt(item);
               stack.addLast(new NumberExpression(value));
            }
        }
        return stack.getLast();
    }

    /**
     * 判断栈顶是否是一个操作符
     * @param stack
     * @return
     */
    private Boolean topIsOperator(LinkedList<String> stack){
    if(stack.isEmpty()){
        return false;
    }
    return Set.of("-","+","*","/").contains(stack.peek());
    }

}

各种表达式的封装

java 复制代码
package club.shengsheng.desigin.combine.compute;

/**
 * 这是计算器表达式的根节点
 */

public interface Expression {

    Integer getValue();

} 

// 符号的处理表达式

public abstract class BinaryOpreationExpression implements Expression {

   private Expression left,  right;

    //
   protected BinaryOpreationExpression(Expression left, Expression right) {
       this.left = left;
       this.right = right;

   }

    @Override
    public Integer getValue() {
        return 0;
    }
}


    


public class AddExpression extends BinaryOpreationExpression {

    private Expression left , right;

   public AddExpression(Expression left, Expression right) {
       super(left, right);
        this.left = left;
        this.right = right;
    }



    @Override
    public Integer getValue() {
        return  this.left.getValue() + this.right.getValue();
    }
}



public class DevisionExpression extends BinaryOpreationExpression {

    NumberExpression left , right;

   public DevisionExpression(Expression left, Expression right) {
       super(left, right);
    }



    @Override
    public Integer getValue() {
        return  this.left.getValue() / this.right.getValue();
    }
}


public class MultiplyExpression extends BinaryOpreationExpression {

    Expression left , right;

   public MultiplyExpression(Expression left, Expression right) {
       super(left, right);
       this.left =  left;
       this.right = right;
    }



    @Override
    public Integer getValue() {
        return  this.left.getValue() * this.right.getValue();
    }
}



public class SubstractExpression extends BinaryOpreationExpression {

    NumberExpression left , right;

   public SubstractExpression(Expression left, Expression right) {
       super(left, right);
    }

    @Override
    public Integer getValue() {
        return  this.left.getValue() - this.right.getValue();
    }
}

// 数字表达式
public class NumberExpression implements Expression {

    private Integer value;

    @Override
    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public NumberExpression(Integer value) {
        this.value = value;
    }


}

最终的结果实现

java 复制代码
public class Main {

    public static void main(String[] args) {
            ExpressionParser expressionParser = new ExpressionParser("22+(2-(5*3))");
            Expression parse = expressionParser.parse();
            System.out.println(parse.getValue());
    }

    public static void test(){
        String item = "+";
        System.out.println( item.equals("+") );
    }
}
相关推荐
IT小白架构师之路13 小时前
常用设计模式系列(十八)-责任链模式
设计模式·责任链模式
源代码•宸21 小时前
深入浅出设计模式——行为型模式之观察者模式 Observer
开发语言·c++·经验分享·观察者模式·设计模式·raii
快起来别睡了1 天前
前端设计模式:让代码更优雅的“万能钥匙”
前端·设计模式
使二颗心免于哀伤2 天前
《设计模式之禅》笔记摘录 - 14.组合模式
笔记·设计模式·组合模式
原则猫2 天前
装饰器工程运用-埋点
设计模式
愿天堂没有C++2 天前
剑指offer第2版——面试题2:实现单例
c++·设计模式·面试
静谧之心2 天前
分层架构下的跨层通信:接口抽象如何解决反向调用
java·开发语言·设计模式·架构·golang·k8s·解耦
用户84913717547163 天前
JustAuth实战系列(第5期):建造者模式进阶 - AuthRequestBuilder设计解析
java·设计模式·架构
只因在人海中多看了你一眼3 天前
B.10.01.5-电商系统的设计模式应用实战
设计模式
希望_睿智3 天前
实战设计模式之代理模式
c++·设计模式·架构