设计模式-组合模式

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

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("+") );
    }
}
相关推荐
syt_10131 天前
设计模式之-代理模式
设计模式·代理模式
拾忆,想起1 天前
设计模式:软件开发的可复用武功秘籍
开发语言·python·算法·微服务·设计模式·性能优化·服务发现
老朱佩琪!1 天前
Unity桥接模式
unity·设计模式·c#·桥接模式
小明的小名叫小明1 天前
Solidity入门(10)-智能合约设计模式1
设计模式·区块链·智能合约
小明的小名叫小明1 天前
Solidity入门(11)-智能合约设计模式2
设计模式·区块链·智能合约
__万波__1 天前
二十三种设计模式(十四)--命令模式
java·设计模式·命令模式
程序员zgh1 天前
C++常用设计模式
c语言·数据结构·c++·设计模式
山风wind1 天前
设计模式-模板方法模式详解
python·设计模式·模板方法模式
郝学胜-神的一滴1 天前
Linux线程的共享资源与非共享资源详解
linux·服务器·开发语言·c++·程序人生·设计模式