JAVA23种设计模式(4)-行为型模式11种-2

JAVA23种设计模式(4)-行为型模式11种2

1.策略模式(Strategy)

原理:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类具体设定行为对象.

 //1.定义行为算法基类 
public interface IDance {
    void beginDance();
}
//2.定义Idance的子类1.不会跳舞
public class SimpleDance implements IDance {

    @Override
    public void beginDance() {
        System.out.println("不会跳舞");
    }
}
//3.定义行为算法Idance的子类2--探戈
public class TangoDance implements IDance  {

    @Override
    public void beginDance() {
        System.out.println("开始跳探戈了");
    }
}
//4.定义基类ISwin 游泳的基类
public interface ISwin {

  void beginSwin();

}
//5.定义不会游泳为Idance的子类1
public class SimpleSwin implements ISwin {

    @Override
    public void beginSwin() {
        System.out.println("不会游泳");
    }

}
//6.定义狗带式游泳为基类算法2
public class DogSwin implements ISwin {

    @Override
    public void beginSwin() {
        System.out.println("狗带式游泳");
    }

}
//7.开始定义使用者的基类,有两个接口作为成员变量
public  class AbsHuman {

   private IDance  mDance;
   private ISwin mSwin;

    public AbsHuman()
    {
        mDance=new SimpleDance();
        mSwin=new SimpleSwin();

    }
    //提供了公共方法去切换两个成员变量的实现
    public void changeSwin(ISwin swin)
    {
        mSwin=swin;
    }

    public void changeDance(IDance dance)
    {
        mDance=dance;
    }
    //使用不同的展现
    public void beginDance()
    {
        mDance.beginDance();
    }


    public void beginSwin()
    {
        mSwin.beginSwin();
    }
}
//8.进行切换测试
public class Main {
    public static void main(String[] args) {

        AbsHuman human=new AbsHuman();
        human.beginDance();
        human.beginSwin();
        System.out.println("___________________");
        System.out.println("开始更换算法");
        human.changeDance(new TangoDance());
        human.changeSwin(new DogSwin());
        human.beginDance();
        human.beginSwin();
    }
}

这个模式就体现对修改关闭,对扩展开放原则的开闭原则,当需求改动的时候,不要在原有代码上去进行注释,写代码.而是我提供算法族的接口,用不同的实现类去切换.这就是非常简单的实现插件式的热拔插效果,这个模式非常有用,大家好好体会

2.命令模式(Command)

原理:将请求/命令/动作封装成对象,这样可以让项目使用这些对象来参数化其他对象,使命令的请求者和执行者可以解耦.

任何状况下,所能观察到得单元越小越具有拓展性,比如,我们研究化学只能在分子状态下得时候,那么我们基本还是属于实验化学去达成我们想要的化合物,但是当我们的研究深入到原子层面的时候,我们可以根据以往研究出来化学原理去探索生产新的化合物.
设计也是相同的道理,越是复杂的设计,越需要细小的单元,命令模式核心就是建立在细小单元完成的复杂设计.

//1.以"命令"作为单元的基类
public interface Command {
    //每个命令有一个执行的方法
    public void execute();
    //同样,每个命令会有一个撤销的方法
    public void undo();
}
//2. 命令单元的默认状态空实现是很有必要的,就像数字中的0,重要的状态
public class NoCommand implements Command {
    @Override
    public void execute() {
    }
    @Override
    public void undo() {
    }
}
//3.设定一个命令可以由多条命令组成的宏命令
public class MarcoCommand implements Command {
    //用数组这种数据结构装下
    private Command[] commands;
    public MarcoCommand(Command[] commands) {
        this.commands = commands;
    }
    //执行宏命令--也就是将数组每一条命令取出来一一执行
    @Override
    public void execute() {
        for (int i = 0, len = commands.length; i < len; i++) {
            commands[i].execute();
        }
    }
    //撤销宏命令--也就是将数组每一条宏命令取出来一一撤销
    @Override
    public void undo() {
        for (int i = commands.length - 1; i >= 0; i--) {
            commands[i].undo();

        }
    }

}
//4.设定命令的单元的执行主体-"灯"
public class Light {
    String loc = "";
    public Light(String loc) {
        this.loc = loc;
    }
    public void On() {

        System.out.println(loc + " On");
    }
    public void Off() {

        System.out.println(loc + " Off");
    }

}
//5."关灯"的命令
public class LightOffCommand implements Command {
    private Light light;
    public LightOffCommand(Light light)
    {
        this.light=light;
    }
    //执行当然就是关灯
    @Override
    public void execute() {
        light.Off();
    }
    //撤销就是开灯
    @Override
    public void undo() {
        light.On();
    }

}
//6.开灯的命令
public class LightOnCommand implements Command {
    private Light light;
    public LightOnCommand(Light light)
    {
        this.light=light;
    }
    //执行就是开灯
    @Override
    public void execute() {
        // TODO Auto-generated method stub
        light.On();
    }
    //撤销就是关灯
    @Override
    public void undo() {
        light.Off();
    }
}
//7.设定命令的第二个主体,有音量属性,开/关/提高/降低 等操作函数
public class Stereo {
    private int volume = 0;
    public void On() {
        System.out.println("Stereo On");
    }

    public void Off() {
        System.out.println("Stereo Off");
    }

    public void SetCd() {
        System.out.println("Stereo SetCd");
    }

    public void SetVol(int vol) {
        volume = vol;
        System.out.println("Stereo volume=" + volume);
    }

    public int GetVol() {
        return volume;
    }

    public void Start() {
        System.out.println("Stereo Start");
    }
}
//8.打开音响的命令
public class StereoOnCommand implements Command {
    private Stereo setreo;
    public StereoOnCommand(Stereo setreo)
    {
        this.setreo=setreo;
    }
    @Override
    public void execute() {
        setreo.On();
        setreo.SetCd();

    }
    @Override
    public void undo() {
        setreo.Off();
    }
}
//9.关闭音响的命令
public class StereoOffCommand implements Command {
    private Stereo setreo;
    public StereoOffCommand(Stereo setreo)
    {
        this.setreo=setreo;
    }

    @Override
    public void execute() {
        // TODO Auto-generated method stub
        setreo.Off();
    }

    @Override
    public void undo() {
        // TODO Auto-generated method stub
        setreo.On();
        setreo.SetCd();
    }

}
//10.增加音量的命令
public class StereoAddVolCommand implements Command {
    private Stereo setreo;
    public StereoAddVolCommand(Stereo setreo)
    {
        this.setreo=setreo;
    }

    @Override
    public void execute() {
    int vol=    setreo.GetVol();
    if(vol<11)
    {
        setreo.SetVol(++vol);
    }

    }

    @Override
    public void undo() {
    int vol=    setreo.GetVol();
    if(vol>0)
    {
        setreo.SetVol(--vol);
    }

    }

}
//11.降低音量的命令
public class StereoSubVolCommand implements Command {
    private Stereo setreo;
    public StereoSubVolCommand(Stereo setreo)
    {
        this.setreo=setreo;
    }

    @Override
    public void execute() {
    int vol=    setreo.GetVol();
    if(vol>0)
    {
        setreo.SetVol(--vol);
    }

    }

    @Override
    public void undo() {
    int vol=    setreo.GetVol();
    if(vol<11)
    {
        setreo.SetVol(++vol);
    }

    }

}
//12.使用遥控器--对操作单元进行操作,slot的遥控器哪个插口
public class CommandModeControl  {
    private Command[] onCommands;
    private Command[] offCommands;
    private Stack<Command> stack=new Stack<Command>();
    public CommandModeControl()
    {
        //给了5个开启命令,5个关闭命令
        onCommands=new Command[5];
         offCommands=new Command[5];
        //初始化的时候将空实现带入所有插口中
         Command noCommand=new NoCommand();

         for(int i=0,len=onCommands.length;i<len;i++)
         {
             onCommands[i]=noCommand;
             offCommands[i]=noCommand;
         }

    }

    //给每个插口带入命令,,对应一个开,一个关闭
    public void setCommand(int slot,Command onCommand,Command offCommand)
    {
        onCommands[slot]=onCommand;
         offCommands[slot]=offCommand;

    }

    public void onButton(int slot) {

        onCommands[slot].execute();
        stack.push(onCommands[slot]);
    }

    public void offButton(int slot) {

        offCommands[slot].execute();
        stack.push(offCommands[slot]);
    }
    //使用栈数据结构,好处,push多少个命令,就可以pop多少个命令,非常棒
    public void undoButton() {
        stack.pop().undo();
    }
}
//13.这是命令模式的测试
public class ControlTest {

    public static void main(String[] args) {
        CommandModeControl control = new CommandModeControl();

        //设定复杂命令的宏操作
        MarcoCommand onmarco,offmarco;

        //操作实体的灯以及开关
        Light bedroomlight = new Light("BedRoom");
        Light kitchlight = new Light("Kitch");
        Stereo stereo = new Stereo();


        //两个灯的开与关
        LightOnCommand bedroomlighton = new LightOnCommand(bedroomlight);
        LightOffCommand bedroomlightoff = new LightOffCommand(bedroomlight);
        LightOnCommand kitchlighton = new LightOnCommand(kitchlight);
        LightOffCommand kitchlightoff = new LightOffCommand(kitchlight);
        //宏命令的开与关
         Command[] oncommands={bedroomlighton,kitchlighton};
         Command[] offcommands={bedroomlightoff,kitchlightoff}; 
        onmarco=new MarcoCommand(oncommands);
        offmarco=new MarcoCommand(offcommands);
        //音响的开与关
        StereoOnCommand stereoOn = new StereoOnCommand(stereo);
        StereoOffCommand stereoOff = new StereoOffCommand(stereo);
        StereoAddVolCommand stereoaddvol = new StereoAddVolCommand(stereo);
        StereoSubVolCommand stereosubvol = new StereoSubVolCommand(stereo);
        //开始为控制器的每个开关赋值,对应了5个插槽
        control.setCommand(0, bedroomlighton, bedroomlightoff);
        control.setCommand(1, kitchlighton, kitchlightoff);
        control.setCommand(2, stereoOn, stereoOff);
        control.setCommand(3, stereoaddvol, stereosubvol);
        control.setCommand(4, onmarco, offmarco);

        //这是进行操作
        control.onButton(0);
        control.undoButton();
        //control.offButton(0);
        control.onButton(1);
        control.offButton(1);
        control.onButton(2);
        control.onButton(3);

        control.offButton(3);
        control.undoButton();
        control.offButton(2);
        control.undoButton();
        control.onButton(4);
        control.offButton(4);
    }

}
即便不使用命令模式也可以做出上面的效果,但是使用命令模式的好处--
代码中的操作实体(灯,音响),命令(执行,撤销),控制器(插槽)都完全解耦了,如果进行拓展,或者修改,能将影响降低到最小

3.备忘录模式(Memento)

原理:在不破坏封装的前提下,存储关键对象的重要状态,从而可以在将来把对象还原到存储的那个状态

具体就是定义一个Memonto接口,然后用一个MementoManager去管理这个接口,随后不管什么样的使用场景,都到MementoManager这个缓冲进行保存.

//1.定义一个备忘录接口
public interface MementoInterface {
}
//2.定义备忘录管理类,作为缓冲保留着,另外这个缓冲在初始化程序的时候需要加载
public class MementoManager {
    private HashMap<String,MementoInterface> mementoMap;

    public MementoManager()
    {
        mementoMap=new HashMap<String,MementoInterface>();
    }

    //保存备忘录
    public void saveMemonto(String name, MementoInterface memento) {
        this.mementoMap.put(name, memento);
    }
    //提取备忘录
    public  MementoInterface retrieveMemento(String key)
    {
        return mementoMap.get(key);
    }


    //TODO 方法1 程序初始化的时候 需要从本地将持久化数据读出
    //TODO 方法2 程序结束的时候  需要将缓存中的数据持久化到本地哦
}
//3.使用场景A中保存状态的备忘录
public class Studio_A_Memento implements MementoInterface{
    private TreeMap<String,String> state;
    public Studio_A_Memento(TreeMap<String,String> save)
    {
        state=new TreeMap<String,String>(save);
    }

     public TreeMap<String,String> getState()
     {
         return state;
     }

     public void setState(TreeMap<String,String> save)
     {
         state=save;
     }

}
//4.使用场景A 的状态 打包备忘录,解包备忘录
public class User_Studio_A {
    private TreeMap<String, String> state;//状态

    public User_Studio_A()
    {
        state=new TreeMap<String, String>();
    }
    //将状态打包成一个备忘录
    public MementoInterface createMemento()
    {
        return new Studio_A_Memento(state);
    }
    //从备忘录中获得状态
    public void restoreMemento(MementoInterface memento)
    {
        state=((Studio_A_Memento)memento).getState();
    }

    public void showState() {
        System.out.println("now state:" + state.toString());
    }
    //测试状态增加1
    public void testState1() {
        state.put("blood", "500");
        state.put("progress", "gate1 end");
        state.put("enemy", "5");

    }
    //测试状态增加2
    public void testState2() {

        state.put("blood", "450");
        state.put("progress", "gate3 start");
        state.put("enemy", "3");

    }
}
//5.使用场景B中保存状态的备忘录
public class Studio_B_Memento implements MementoInterface {
    private ArrayList<String> state;

    public Studio_B_Memento(ArrayList<String> save) {
        state = new ArrayList<String>(save);
    }
    public ArrayList<String> getState() {
        return state;
    }
    public void setState(ArrayList<String> save) {
        state = save;
    }
}
//6.使用场景B 的状态 打包备忘录,解包备忘录
public class User_Studio_B {
    private ArrayList<String> state;

    public User_Studio_B()
    {
        state=new ArrayList<String>();
    }
    //将状态打包成一个备忘录
    public MementoInterface createMemento()
    {
        return new Studio_B_Memento(state);
    }
    //从备忘录中获得状态
    public void restoreMemento(MementoInterface memento)
    {
        state=((Studio_B_Memento)memento).getState();
    }


    public void testState1() {
        state = new ArrayList<String>();
        state.add("blood:320");
        state.add("progress:gate2 mid");
        state.add("enemy:15");

    }

    public void testState2() {
        state = new ArrayList<String>();
        state.add("blood:230");
        state.add("progress:gate8 last");
        state.add("enemy:12");

    }

    public void showState() {
        System.out.println("now state:" + state.toString());
    } 
}

优点:
1.状态存储在外面.不和关键对象混在一起,可以帮助维护内聚
2.提供容易实现的恢复能力
3.保持关键对象的数据封装
缺点:
1.资源消耗上备忘录对象会很昂贵
2.存储和恢复过程很耗时

适用场合:
必须保存一个对象在某一个时刻的(整体或部分)状态,在对象以外的地方,以后需要时恢复到先前的状态

4.状态模式(state)

原理:根据内部状态的变化,改变对象的行为,看起来好像是修改了类.

如果采用一般的方法去做,是在每个方法中使用switch()分支,根据不同的状态执行不同的语句,可是,假如在需要拓展的时候,就在switch中增加case,如果想要封装性更加良好.因此考虑将状态抽象出来成为接口.

//1.定义状态接口,实现类是各种状态下的售货机的行为
public interface State {
    //插入硬币
    void insertCoin();
    //退换硬币
    void getBackCoin();
    //旋转把手
    void turnCrank();
    //放出可乐
    void offerCoke();
    //打印状态
    void printState();
}
//2.定义一个自动售货机 出售可乐
public class ColaMachine {
    //当前状态接口
    private State currenState;
    //当前可乐数量
    private int count = 0; 

    //5种状态的实现类
    State mSoldOutState;
    State mOnReadyState;
    State mHasCoin;
    State mSoldState;
    State mWinnerState;

    public ColaMachine(int cou)
    {
        count=cou;
        mSoldOutState = new SoldOutState(this);
        mOnReadyState = new OnReadyState(this);
        mHasCoin = new HasCoinState(this);
        mSoldState = new SoldState(this);
        mWinnerState = new WinnerState(this);

        if (count > 0) {
            currenState = mOnReadyState;
        } else {
            currenState = mSoldOutState;
        }
    }

    public int getCount() {
        return count;
    }

    public void setCurrenState(State currenState) {
        this.currenState = currenState;
    }


    //提供4个方法给用户使用 投币,返回硬币,转动出货把手,检查状态
    public void insertCoin() {
        currenState.insertCoin();
    }

    public void returnCoin() {
        currenState.getBackCoin();
    }

    public void turnCrank() {
        currenState.turnCrank();
        currenState.offerCoke();
    }
    public void printstate() {
        currenState.printState();
    }

    //提供 给状态的各个实现类使用
    void releaseCandy() {
        if (count > 0) {
            count = count - 1;
            System.out.println("a cola rolling out!");
        }
    }
}
import java.util.Random;
//3.定义state接口实现类1.有硬币状态
public class HasCoinState implements State {

    private ColaMachine mColaMachine;

    public HasCoinState(ColaMachine colaMachine)
    {
        this.mColaMachine = colaMachine;
    }

    @Override
    public void insertCoin() {
        System.out.println("you can't insert another coin!");

    }

    @Override
    public void getBackCoin() {
        System.out.println("coin return!");
        mColaMachine.setCurrenState(mColaMachine.mOnReadyState);

    }

    @Override
    public void turnCrank() {
        System.out.println("crank turn...!");
        Random winnerRandom = new Random();
        int winner = winnerRandom.nextInt(10);
        if(winner==10){
            mColaMachine.setCurrenState(mColaMachine.mWinnerState);
        }
        else
        {
            mColaMachine.setCurrenState(mColaMachine.mSoldState);

        }


    }

    @Override
    public void offerCoke() {

    }

    @Override
    public void printState() {
        System.out.println("***HasCoinState***");
    }

}

//4.定义state接口实现类2. 准备状态
public class OnReadyState implements State {

    private ColaMachine mColaMachine;

    public OnReadyState(ColaMachine colaMachine)
    {
        this.mColaMachine = colaMachine;
    }

    @Override
    public void insertCoin() {
        System.out.println("you have inserted a coin,next,please turn crank!");
        mColaMachine.setCurrenState(mColaMachine.mHasCoin);

    }

    @Override
    public void getBackCoin() {
        System.out.println("you haven't inserted a coin yet!");

    }

    @Override
    public void turnCrank() {
        System.out.println("you turned,but you haven't inserted a coin!");

    }

    @Override
    public void offerCoke() {


    }

    @Override
    public void printState() {
        System.out.println("***OnReadyState***");

    }

}
//5.状态接口的实现类3-卖完状态
public class SoldOutState implements State {

    private ColaMachine mColaMachine;

    public SoldOutState(ColaMachine colaMachine) {
        this.mColaMachine = colaMachine;
    }

    // 卖完状态的插入硬币
    @Override
    public void insertCoin() {

        System.out.println("you can't insert coin,the machine sold out!");

    }

    // 卖完状态的旋转把手
    @Override
    public void turnCrank() {

        System.out.println("you turned,but there are no  cola!");

    }

    // 卖完状态的拿回硬币
    @Override
    public void getBackCoin() {
        System.out.println("you can't get coin back,the machine sold out!");

    }

    // 卖完状态下的无法提供可乐
    @Override
    public void offerCoke() {

    }

    // 卖完状态下的打印状态
    @Override
    public void printState() {
        System.out.println("***SoldOutState***");

    }

}
//6.状态接口的实现类4-正在出可乐状态状态
public class SoldState implements State {

    private ColaMachine mColaMachine;

    public SoldState(ColaMachine colaMachine) {
        this.mColaMachine = colaMachine;
    }

    @Override
    public void insertCoin() {
        System.out.println("please wait!we are giving you a candy!");

    }

    @Override
    public void getBackCoin() {
        System.out.println("you haven't inserted a coin yet!");

    }

    @Override
    public void turnCrank() {

        System.out.println("we are giving you a candy,turning another get nothing,!");
    }

    @Override
    public void offerCoke() {
        mColaMachine.releaseCandy();
        if (mColaMachine.getCount() > 0) {
            mColaMachine.setCurrenState(mColaMachine.mOnReadyState);
        } else {
            System.out.println("Oo,out of candies");
            mColaMachine.setCurrenState(mColaMachine.mSoldOutState);
        }

    }

    @Override
    public void printState() {
        System.out.println("***SoldState***");

    }

}
//7.状态接口的实现类5-赢家状态-有一定几率多出一个
public class WinnerState implements State {

    private ColaMachine mColaMachine;

    public WinnerState(ColaMachine colaMachine)
    {
        this.mColaMachine = colaMachine;
    }

    @Override
    public void insertCoin() {

        System.out.println("please wait!we are giving you a candy!");

    }

    @Override
    public void getBackCoin() {
        System.out.println("you haven't inserted a coin yet!");


    }

    @Override
    public void turnCrank() {
        System.out.println("we are giving you a candy,turning another get nothing,!");

    }

    @Override
    public void offerCoke() {
        mColaMachine.releaseCandy();
        if (mColaMachine.getCount() == 0) {
            mColaMachine.setCurrenState(mColaMachine.mSoldOutState);
        } else {
            System.out.println("you are a winner!you get another candy!");
            mColaMachine.releaseCandy();
            if (mColaMachine.getCount() > 0) {
                mColaMachine.setCurrenState(mColaMachine.mOnReadyState);
            } else {
                System.out.println("Oo,out of candies");
                mColaMachine.setCurrenState(mColaMachine.mSoldOutState);
            }
        }

    }

    @Override
    public void printState() {
        System.out.println("***WinnerState***");


    }

}
//8.代码测试
public class Main {


    public static void main(String[] args) {

        ColaMachine machine=new ColaMachine(6);


        machine.printstate();

        machine.insertCoin();
        machine.printstate();

        machine.turnCrank();

        machine.printstate();

        machine.insertCoin();
        machine.printstate();

        machine.turnCrank();

        machine.printstate();

    }

}

从代码中可以看出,将一个耦合性很高的类,使用接口将它的状态从属性中解耦出来,变成一个可以拓展的体系.

5.解释器模式(interpreter)

解释器模式:定义一个语法,定义一个解释器,该解释器处理该语法句子,将某些复杂问题,表达为某种语法规则,然后构建解释器来处理这类句子.

这一般是遇到了大数据分析套用公式进行计算的情况下进行处理
计算模型一般需要解释的有两种符号:
1.数据
2.计算符

由于计算机无法理解人类看算式的优先级,这里采用逆波兰算法

维基百科里的逆波兰算法

这里写图片描述

import java.util.HashMap;
//1.定义符号表达式统一的抽象基类
public abstract class AbstractExpresstion {
    //传入一列数据
    public abstract Float interpreter(HashMap<String, Float> var);
}
import java.util.HashMap;
//2.变量的符号
public class VarExpresstion extends AbstractExpresstion {
    private String key;

    public VarExpresstion(String _key) {
        this.key = _key;
    }
//普通的变量就是 变量代表的数值
    @Override
    public Float interpreter(HashMap<String, Float> var) {
        return var.get(this.key);
    }
}
//3.符号的分支-运算符,在逆波兰运算中,运算符是终结符
public abstract class SymbolExpresstion extends AbstractExpresstion {
    protected AbstractExpresstion left;
    protected AbstractExpresstion right;

    public SymbolExpresstion(AbstractExpresstion _left,
            AbstractExpresstion _right) {
        this.left = _left;
        this.right = _right;
    }
}
//4."+"符号的
public class AddExpresstion extends SymbolExpresstion {

    public AddExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
        super(_left, _right);
    }

    @Override
    public Float interpreter(HashMap<String, Float> var) {
        return super.left.interpreter(var) + super.right.interpreter(var);
    }

}
//5."-"符号
public class SubExpresstion extends SymbolExpresstion {

    public SubExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
        super(_left, _right);
    }

    @Override
    public Float interpreter(HashMap<String, Float> var) {
        return super.left.interpreter(var) - super.right.interpreter(var);
    }
}
//6."*"乘符号
public class MultiExpresstion extends SymbolExpresstion {

    public MultiExpresstion(AbstractExpresstion _left,
            AbstractExpresstion _right) {
        super(_left, _right);
    }
    @Override
    public Float interpreter(HashMap<String, Float> var) {
        return super.left.interpreter(var) * super.right.interpreter(var);
    }
}
//7."/" 除法符号
public class DivExpresstion extends SymbolExpresstion {

    public DivExpresstion(AbstractExpresstion _left, AbstractExpresstion _right) {
        super(_left, _right);
    }
    @Override
    public Float interpreter(HashMap<String, Float> var) {
        return super.left.interpreter(var) / super.right.interpreter(var);
    }
}
//8.逆波兰算法-计算机可读懂的栈结构 右序算法
public class RPN {

    private ArrayList<String> expression = new ArrayList<String>();// 存储中序表达式

    private ArrayList<String> right = new ArrayList<String>();// 存储右序表达式

    private AbstractExpresstion result;// 结果

    // 依据输入信息创建对象,将数值与操作符放入ArrayList中
    // 根据自定义字符为分界符进行拆分,并将结果进行封装提供对应方法进行遍历取值,
//  StringTokenizer 方法不区分标识符、数和带引号的字符串,它们也不识别并跳过注释;该方法用途类似于split方法,
    public RPN(String input) {
        // 公式 a+b-c*d+e-f
        StringTokenizer st = new StringTokenizer(input, "+-*/()", true);
        while (st.hasMoreElements()) {
            //中序表达式就这个 链表是: "a","+","b","-","c","*","d","+","e","-","f"
            expression.add(st.nextToken());
        }
    }

    // 将中序表达式转换为右序表达式
    private void toRight() {
        // 1.新建立一个缓存的栈
        Stacks aStack = new Stacks();
        // 2. 符号缓存
        String operator;
        // 3.栈指针 是 position
        int position = 0;
        while (true) {

            if (Calculate.isOperator((String) expression.get(position))) {
              //如果是1个操作符
                if (aStack.top == -1 || ((String) expression.get(position)).equals("(")) {
                    //第一个字符存入缓存
                    aStack.push(expression.get(position));
                } else {
                    if (((String) expression.get(position)).equals(")")) {
                        //如果栈顶不是
                        if (!((String) aStack.top()).equals("(")) {
                            operator = (String) aStack.pop();
                            right.add(operator);
                        }
                    } else {
                        if (Calculate.priority((String) expression.get(position)) <= Calculate.priority((String) aStack.top()) && aStack.top != -1) {
                            operator = (String) aStack.pop();
                            if (!operator.equals("("))
                                right.add(operator);
                        }
                        aStack.push(expression.get(position));
                    }
                }
            } else //如果不是操作符,直接加入
                right.add(expression.get(position));
            position++;
            //如果指针长度多于表达式
            if (position >= expression.size())
                break;
        }
        while (aStack.top != -1) {
            operator = (String) aStack.pop();
            right.add(operator);
        }
    }

    // 对右序表达式进行求值(逆波兰求值)
    public void getResult(HashMap<String, Float> var) {
        this.toRight();
        Stack<AbstractExpresstion> stack = new Stack<AbstractExpresstion>();
        AbstractExpresstion op1, op2;
        String is = null;
        Iterator it = right.iterator();

        while (it.hasNext()) {
            is = (String) it.next();
            if (Calculate.isOperator(is)) {
                op2 = stack.pop();
                op1 = stack.pop();
                stack.push(Calculate.twoResult(is, op1, op2));
            } else
                stack.push(new VarExpresstion(is));
        }
        result = stack.pop();
        it = expression.iterator();
        while (it.hasNext()) {
            System.out.print((String) it.next());
        }
        System.out.println("=" + result.interpreter(var));
    }

    // 计算工具类.
    public static class Calculate {
        // 判断是否为操作符号
        public static boolean isOperator(String operator) {
            if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")
                    || operator.equals("(") || operator.equals(")"))
                return true;
            else
                return false;
        }

        // 设置操作符号的优先级别
        public static int priority(String operator) {
            if (operator.equals("+") || operator.equals("-") || operator.equals("("))
                return 1;
            else if (operator.equals("*") || operator.equals("/"))
                return 2;
            else
                return 0;
        }

        // 做2值之间的计算
        public static AbstractExpresstion twoResult(String op, AbstractExpresstion a, AbstractExpresstion b) {
            try {

                AbstractExpresstion result = null;
                if (op.equals("+"))
                    result = new AddExpresstion(a, b);
                else if (op.equals("-"))
                    result = new SubExpresstion(a, b);
                else if (op.equals("*"))
                    result = new MultiExpresstion(a, b);
                else if (op.equals("/"))
                    result = new DivExpresstion(a, b);
                else
                    ;
                return result;
            } catch (NumberFormatException e) {
                System.out.println("input has something wrong!");
                return null;
            }
        }
    }

    // 栈类
    public class Stacks {
        private LinkedList list = new LinkedList();
        int top = -1;

        public void push(Object value) {
            top++;
            list.addFirst(value);
        }

        public Object pop() {
            Object temp = list.getFirst();
            top--;
            list.removeFirst();
            return temp;

        }

        public Object top() {
            return list.getFirst();
        }
    }
}

//9.模拟一次运算
public class Calculator {

    public Calculator() {
        //随机生成大数据 3组  6个数据
        float[][] dataSource = new float[3][6];
        System.out.println("data source:");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 6; j++) {
                dataSource[i][j] = (float) (Math.random() * 100);
                System.out.print(dataSource[i][j] + ",");
            }
            System.out.println(";");
        }

        try {
            System.out.println("Input a expression:");
            BufferedReader is = new BufferedReader(new InputStreamReader(
                    System.in));
            for (;;) {
                String input = new String();
                input = is.readLine().trim();
                if (input.equals("q"))
                    break;
                else {
                    //输入的公式带入逆波兰算法中
                    RPN boya = new RPN(input);
                    HashMap<String, Float> var;
                    for (int i = 0; i < 3; i++) {
                        var = new HashMap<String, Float>();
                        //三组 的 6个变量分别为a,b,c,d,e,f
                        var.put("a", dataSource[i][0]);
                        var.put("b", dataSource[i][1]);
                        var.put("c", dataSource[i][2]);
                        var.put("d", dataSource[i][3]);
                        var.put("e", dataSource[i][4]);
                        var.put("f", dataSource[i][5]);
                        //计算出结果
                        boya.getResult(var);

                    }

                }
                System.out
                        .println("Input another expression or input 'q' to quit:");
            }
            is.close();
        } catch (IOException e) {
            System.out.println("Wrong input!!!");
        }

    }

}
//10.测试一下
public class MainTest {

    public static void main(String[] args) {
        new Calculator();
    }

}

优点:
1.容易修改,修改语法规则相应非终结符即可
2.托展方便,托展语法,只要增加非终结符即可.
缺点:
1.对于复杂语法的表示会产生复杂的类层次结构,不便管理和维护
2.解释器采用递归方式,效率会受影响

适用场合:
1.当你有一个简单语法,而且效率不是问题的时候
2.一些数据分析工具\报表设计工具\科学计算工具等

尽量不要在重要模块使用解释器模式,使用递归,内存开销比较大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值