设计模式-组合模式

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

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("+") );
    }
}
相关推荐
ST.J1 天前
设计模式笔记
笔记·设计模式
TechNomad1 天前
设计模式:备忘录模式(Memento Pattern)
设计模式·备忘录模式
尘鹄1 天前
go 初始化组件最佳实践
后端·设计模式·golang
小蜗牛在漫步1 天前
23种设计模式-组合模式
设计模式·组合模式
努力也学不会java1 天前
【设计模式】代理模式
java·设计模式·代理模式
会有黎明吗2 天前
设计模式最佳实践 - 模板模式 + 责任链模式
设计模式·责任链模式
聪明墨菲特2 天前
HttpClient工具类优化实践:提升性能与可维护性
后端·设计模式
TechNomad2 天前
设计模式:中介者模式(Mediator Pattern)
设计模式·中介者模式
Meteors.2 天前
23种设计模式——抽象工厂模式(Abstract Factory Pattern)详解
设计模式·抽象工厂模式
使一颗心免于哀伤2 天前
《设计模式之禅》笔记摘录 - 19.备忘录模式
笔记·设计模式