设计模式-组合模式

发布于:2025-07-16 ⋅ 阅读:(13) ⋅ 点赞:(0)

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

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

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

1. 区

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;
    }
}

2. 城市

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();
    }
}

3. 省

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. 示例 用组合模式实现一个计算器的逻辑

package club.shengsheng.desigin.combine.compute;

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

public interface Expression {

    Integer getValue();

}

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

 // 中缀表达式转为后缀表达式
    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;
    }

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

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());
    }

}

各种表达式的封装

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;
    }


}


最终的结果实现 


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("+") );
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到