手机话费的新用途
可视化完全二叉树

状态模式是怎样干掉 case&if 的

obi posted @ 2010年8月02日 01:11 in 未分类 with tags 设计模式 java 状态模式 , 4652 阅读

有一个实例来辅助分析话会更方便,这里使用的实例是:编程找出文件中符合正则表达式 "alpha[alpha|digit]*" 和 "digit+" 的字符串。alpha 就是字母啦:[a-zA-Z];digit就是数字:[0-9]。

先画出DFA:

在上图中,状态只有三个(结束状态可以省略):开始状态、单词状态和数字状态。

接下来要用两种不同的方法来实现这个DFA,第一种是传统的 while&switch 大法,第二种是现在流行的设计模式中的状态模式。

为了方便比较,先抽象出一个名为Parser的接口,它提供了一个名为 parse 的方法,传统状态机状态机模式通过实现这个方法来完成对正则表达式的识别。传统状态机实现的类名叫ClassicalMachine,状态机模式的类名则叫PatternMachine。

Parser接口的定义: 

public interface Parser {
  void parse() throws Exception ;
}

ClassicalMachine 类的实现非常简单,它在 parse() 方法里就完成了干完了一切:

public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}

 注意上面有一堆 case xxx: 和 if(xxx),如果DFA中有更多的状态和动作的话,case xxx: 会更多。

接下来实现状态模式类。从DFA图可以看出需要实现的动作只有三个,这三个动作分别在碰到字母、数字和其它字符时触发,因此可以定义状态抽象类如下:

abstract class State {
    public abstract void isAlpha(char c);
    public abstract void isDigit(char c);
    public abstract void isOther(char c);
}

为了方便判断字符是数字还是字母,再加上一个函数dispatch(),于是State类最终是这样:

abstract class State {
    public abstract void isAlpha(char c);
    public abstract void isDigit(char c);
    public abstract void isOther(char c);
    public void dispatch(char c) {
        if (Character.isLetter(c)) {
            isAlpha(c);
        }
        else if (Character.isDigit(c)) {
            isDigit(c);
        }
        else {
            isOther(c);
        }
    }
}

 再看看上面的DFA图,发现状态只有三个,因此接下来从 State 派生出三个类对应这三个状态: 

class StartState extends State {
    public void isAlpha(char c) {
        setState( mKeywordState );
        mToken += c;
    }
    public void isDigit(char c) {
        setState( mNumberState );
        mToken += c;
    }
    public void isOther(char c) {
    }
}
	
class KeywordState extends State {
    public void isAlpha(char c) {
        mToken += c;
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Keyword: " + mToken);
        mToken = "";
    }
}
	
class NumberState extends State {
    public void isAlpha(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
}

 万事具备,只欠东风了,剩下的只是将字符流作为燃料,来驱动状态机了:

public void parse() throws Exception {
    while (true) {
        int ch = mFin.read();
        if (-1 == ch) break;
        char c = (char)ch;
        mState.dispatch( c );
			
    }
}

 


上面啰啰嗦嗦写了一堆代码,目的就是要对比传统状态机的实现方式和状态模式的区别。传统的实现方式是使用一大块 if&switch 代码,比如说lua的lex;当然也可以对这段铁板代码进行拆分,python的lex就是这么干的,但这样做仅仅只是将那些头痛的switch&if分散到了其它的函数而已,switch&if 和数量并没有减少。更多的条件判断语句会导致更复杂的逻辑,因此要让逻辑变得更简单, 得减少这些判断语句才行---状态模式办到了,它干掉了至少一半的判断语句。它是怎么做到的?

状态机的特点之一:状态是在运行时确定的,这刚好可以通过多态来实现。多态的特点:在运行时对对象进行动态绑定,绑定是由编译器或运行环境来完成的,无需手工参与,因此也可以说是现代越来越强大的编译器or运行环境干掉了switch&if。

附完整的代码:

ClassicalMachine.java:

package bsg;
import java.io.BufferedReader;
import java.io.IOException;


import bsg.Main.Parser;

import com.sun.tools.hat.internal.parser.Reader;


public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}



public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}


abstract class State {
    public abstract void isAlpha(char c);
    public abstract void isDigit(char c);
    public abstract void isOther(char c);
    public void dispatch(char c) {
        if (Character.isLetter(c)) {
            isAlpha(c);
        }
        else if (Character.isDigit(c)) {
            isDigit(c);
        }
        else {
            isOther(c);
        }
    }
}


class StartState extends State {
    public void isAlpha(char c) {
        setState( mKeywordState );
        mToken += c;
    }
    public void isDigit(char c) {
        setState( mNumberState );
        mToken += c;
    }
    public void isOther(char c) {
    }
}
	
class KeywordState extends State {
    public void isAlpha(char c) {
        mToken += c;
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Keyword: " + mToken);
        mToken = "";
    }
}
	
class NumberState extends State {
    public void isAlpha(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
}


public void parse() throws Exception {
    while (true) {
        int ch = mFin.read();
        if (-1 == ch) break;
        char c = (char)ch;
        mState.dispatch( c );
			
    }
}

 PatternMachine.java

package bsg;

import java.io.BufferedReader;

import bsg.Main.Parser;

public class PatternMachine implements Parser {
    private String mToken = "";
    private BufferedReader mFin;
    public PatternMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private StartState mStartState = new StartState();
    private KeywordState mKeywordState = new KeywordState();
    private NumberState mNumberState = new NumberState();
    //
    private State mState = mStartState;
    public State getState() {
        return mState;
    }
    public void setState(State state) {
        mState = state;
    }

    abstract class State {
        public abstract void isAlpha(char c);
        public abstract void isDigit(char c);
        public abstract void isOther(char c);
        public void dispatch(char c) {
            if (Character.isLetter(c)) {
                isAlpha(c);
            }
            else if (Character.isDigit(c)) {
                isDigit(c);
            }
            else {
                isOther(c);
            }
        }
    }
	
    class StartState extends State {
        public void isAlpha(char c) {
            setState( mKeywordState );
            mToken += c;
        }
        public void isDigit(char c) {
            setState( mNumberState );
            mToken += c;
        }
        public void isOther(char c) {
        }
    }
	
    class KeywordState extends State {
        public void isAlpha(char c) {
            mToken += c;
        }
        public void isDigit(char c) {
            mToken += c;
        }
        public void isOther(char c) {
            setState( mStartState );
            System.out.println("Keyword: " + mToken);
            mToken = "";
        }
    }
	
    class NumberState extends State {
        public void isAlpha(char c) {
            setState( mStartState );
            System.out.println("Number: " + mToken);
            mToken = "";
        }
        public void isDigit(char c) {
            mToken += c;
        }
        public void isOther(char c) {
            setState( mStartState );
            System.out.println("Number: " + mToken);
            mToken = "";
        }
    }
	

    @Override
    public void parse() throws Exception {
        while (true) {
            int ch = mFin.read();
            if (-1 == ch) break;
            char c = (char)ch;
            mState.dispatch( c );
			
        }
    }

}


package bsg;
import java.io.BufferedReader;
import java.io.IOException;


import bsg.Main.Parser;

import com.sun.tools.hat.internal.parser.Reader;


public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}



public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}


abstract class State {
    public abstract void isAlpha(char c);
    public abstract void isDigit(char c);
    public abstract void isOther(char c);
    public void dispatch(char c) {
        if (Character.isLetter(c)) {
            isAlpha(c);
        }
        else if (Character.isDigit(c)) {
            isDigit(c);
        }
        else {
            isOther(c);
        }
    }
}


class StartState extends State {
    public void isAlpha(char c) {
        setState( mKeywordState );
        mToken += c;
    }
    public void isDigit(char c) {
        setState( mNumberState );
        mToken += c;
    }
    public void isOther(char c) {
    }
}
	
class KeywordState extends State {
    public void isAlpha(char c) {
        mToken += c;
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Keyword: " + mToken);
        mToken = "";
    }
}
	
class NumberState extends State {
    public void isAlpha(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
}


public void parse() throws Exception {
    while (true) {
        int ch = mFin.read();
        if (-1 == ch) break;
        char c = (char)ch;
        mState.dispatch( c );
			
    }
}

Main.java 

package bsg;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;


public class Main {
    public interface Parser {
        void parse() throws Exception ;
    }
	
    public static void main(String[] args) {
        if (0 == args.length) return;

        BufferedReader fin = null;
        try {
            fin = new BufferedReader( new FileReader(args[1] ) );
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
		
        Parser parser = null;
        if (args[0].equals("cla")) {
            parser = new ClassicalMachine( fin );
        } else if (args[0].equals("pat")){
            parser = new PatternMachine( fin );
        }
		
        long beg = System.currentTimeMillis();
        try {
            parser.parse();
            fin.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis() - beg;
        System.out.println("" + end);
    }
}


package bsg;

import java.io.BufferedReader;

import bsg.Main.Parser;

public class PatternMachine implements Parser {
    private String mToken = "";
    private BufferedReader mFin;
    public PatternMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private StartState mStartState = new StartState();
    private KeywordState mKeywordState = new KeywordState();
    private NumberState mNumberState = new NumberState();
    //
    private State mState = mStartState;
    public State getState() {
        return mState;
    }
    public void setState(State state) {
        mState = state;
    }

    abstract class State {
        public abstract void isAlpha(char c);
        public abstract void isDigit(char c);
        public abstract void isOther(char c);
        public void dispatch(char c) {
            if (Character.isLetter(c)) {
                isAlpha(c);
            }
            else if (Character.isDigit(c)) {
                isDigit(c);
            }
            else {
                isOther(c);
            }
        }
    }
	
    class StartState extends State {
        public void isAlpha(char c) {
            setState( mKeywordState );
            mToken += c;
        }
        public void isDigit(char c) {
            setState( mNumberState );
            mToken += c;
        }
        public void isOther(char c) {
        }
    }
	
    class KeywordState extends State {
        public void isAlpha(char c) {
            mToken += c;
        }
        public void isDigit(char c) {
            mToken += c;
        }
        public void isOther(char c) {
            setState( mStartState );
            System.out.println("Keyword: " + mToken);
            mToken = "";
        }
    }
	
    class NumberState extends State {
        public void isAlpha(char c) {
            setState( mStartState );
            System.out.println("Number: " + mToken);
            mToken = "";
        }
        public void isDigit(char c) {
            mToken += c;
        }
        public void isOther(char c) {
            setState( mStartState );
            System.out.println("Number: " + mToken);
            mToken = "";
        }
    }
	

    @Override
    public void parse() throws Exception {
        while (true) {
            int ch = mFin.read();
            if (-1 == ch) break;
            char c = (char)ch;
            mState.dispatch( c );
			
        }
    }

}


package bsg;
import java.io.BufferedReader;
import java.io.IOException;


import bsg.Main.Parser;

import com.sun.tools.hat.internal.parser.Reader;


public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}



public class ClassicalMachine implements Parser {
    private BufferedReader mFin;
    private String mToken;
	
    public ClassicalMachine( BufferedReader fin ) {
        mFin = fin;
    }
	
    private enum STATUS {START, IS_KEYWORD, IS_NUMBER};
    STATUS mStatus = STATUS.START;

    @Override
    public void parse() throws Exception {
        mToken = "";
        while (true) {
            int ch = mFin.read();
            if (-1 == ch)	break;
            char c = (char)ch;

            switch (mStatus) {
            case START:
                if (Character.isLetter(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_KEYWORD;
                }
                else if (Character.isDigit(c)) {
                    mToken += c;
                    mStatus = STATUS.IS_NUMBER;
                }
                break;

            case IS_KEYWORD:
                if (Character.isLetterOrDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("keyword: " + mToken);
                    mToken = "";
                }
                break;

            case IS_NUMBER:
                if (Character.isDigit(c)) {
                    mToken += c;
                }
                else {
                    mStatus = STATUS.START;
                    System.out.println("number: " + mToken);
                    mToken = "";
                }
                break;
            }
        }
    }
	
}


abstract class State {
    public abstract void isAlpha(char c);
    public abstract void isDigit(char c);
    public abstract void isOther(char c);
    public void dispatch(char c) {
        if (Character.isLetter(c)) {
            isAlpha(c);
        }
        else if (Character.isDigit(c)) {
            isDigit(c);
        }
        else {
            isOther(c);
        }
    }
}


class StartState extends State {
    public void isAlpha(char c) {
        setState( mKeywordState );
        mToken += c;
    }
    public void isDigit(char c) {
        setState( mNumberState );
        mToken += c;
    }
    public void isOther(char c) {
    }
}
	
class KeywordState extends State {
    public void isAlpha(char c) {
        mToken += c;
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Keyword: " + mToken);
        mToken = "";
    }
}
	
class NumberState extends State {
    public void isAlpha(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
    public void isDigit(char c) {
        mToken += c;
    }
    public void isOther(char c) {
        setState( mStartState );
        System.out.println("Number: " + mToken);
        mToken = "";
    }
}


public void parse() throws Exception {
    while (true) {
        int ch = mFin.read();
        if (-1 == ch) break;
        char c = (char)ch;
        mState.dispatch( c );
			
    }
}

 

 

e Challan AP 说:
2022年8月05日 22:08

Challan issuing for traffic violation now fully brought online by the state as e Challan AP. The official website built to bring easier process for traffic police in Andhra Pradesh is apechallan.org. Any challan imposed on vehicles or drivers through integrated installed camera or traffic police may directly updated in official website. e Challan AP The online website does help the traffic police to track the vehicle moving on road if any violation and as well it brings a quick process for citizens who issued with an e Challan to clear their dues. Online system has made everyone strictly follow the rules of traffic, as any minute violation does lead to an e Challan.

AP SSC sa 2 Model Pa 说:
2022年9月09日 03:44

SA-2 Exams called Summative Assignment-2 exams are known as Annual final public exams, every year those exams are held at the end of the academic session as Term-2 exams. Every State Board Telugu Medium, AP SSC sa 2 Model Paper English Medium & Urdu Medium Students can download the AP 10th Class SA 2 Model Paper 2023 Pdf with Answer Solutions designed by the Board based on the revised syllabus and curriculum.Class teachers and others have designed and suggested the AP 10th Class SA 2 Model Paper 2023 for all languages and subjects of the course for theory, objective,

pavzi.com 说:
2024年1月19日 22:16

Pavzi.com is a startup by passionate webmasters and bloggers who have a passion for providing engaging content that is accurate, interesting, and worthy to read. pavzi.com We are more like a web community where you can find different information, resources, and topics on day-to-day incidents or news. We provide you with the finest web content on every topic possible with the help of the editorial and content team.

스포츠토토 说:
2024年3月28日 11:13

I am really impressed with your writing skills well with the layout for your weblog. Is that this a paid subject matter or did you modify it your self? Anyway stay up the nice high quality writing, it is rare to see a nice weblog like this one these days

토토사이트추천 说:
2024年3月28日 11:35

Greetings! I know this is kinda off topic but I’d figured I’d ask. Would you be interested in trading links or maybe guest authoring a blog article or vice-versa? My site addresses a lot of the same subjects as yours and I believe we could greatly benefit from each other. If you are interested feel free to send me an e-mail. I look forward to hearing from you! Wonderful blog by the way!

먹튀검증 说:
2024年3月28日 11:36

An interesting discussion is worth comment. I think that you should write more on this topic, it might not be a taboo subject but generally people are not enough to speak on such topics. To the next. Cheers

먹튀검증사이트 说:
2024年3月28日 11:36

Efficient chance management is essential when working with crypto arbitrage bots. Despite their benefits, they're perhaps not resistant to advertise fluctuations. Traders should identify apparent risk variables and frequently monitor bot efficiency to arrange with their strategies.

온라인카지노 说:
2024年3月28日 11:52

Investigate the potential of algorithmic stablecoin arbitrage methods, as stablecoins are a critical part of the cryptocurrency ecosystem and their prices can differ across different exchanges.

먹튀폴리스보증업체 说:
2024年3月28日 11:53

I have been hoping to track down a comfort or clear construction to turn up at ground zero. I have been hoping to track down a comfort or clear construction to turn up at ground zero. Grateful to you for dropping this story. I will obviously be returning in the future to your blog for absolutely more. I respect your brief and reasonable information.

스포츠토토사이트 说:
2024年3月28日 11:53

Hi there! Quick question that’s entirely off topic. Do you know how to make your site mobile friendly? My web site looks weird when browsing from my iphone. I’m trying to find a template or plugin that might be able to fix this problem. If you have any recommendations, please share. Many thanks!

먹튀지키미 说:
2024年3月28日 11:53

What i do not realize is in reality how you’re now not actually much more neatly-favored than you may be right now. You’re very intelligent. You recognize therefore considerably relating to this topic, made me in my view consider it from a lot of varied angles. Its like women and men aren’t involved until it’s one thing to do with Girl gaga! Your own stuffs excellent. Always maintain it up!

바카라 说:
2024年3月28日 11:54

satisfactory article if u searching out real-time a laugh first-rate evening desert safari dubai and incredible tour applications at an inexpensive charge then u contact the enterprise. That is a incredible article thanks for sharing this informative information. I'm able to visit your blog frequently for some modern-day publish. I can visit your weblog often for a few modern put up. Awesome blog. I enjoyed analyzing your articles. That is certainly a exquisite study for me. I have bookmarked it and i am searching forward to reading new articles. Maintain up the best work! Thanks for the valuable information and insights you have so supplied right here..

먹튀신고 说:
2024年3月28日 11:55

Greetings! I know this is kinda off topic but I’d figured I’d ask. Would you be interested in trading links or maybe guest authoring a blog article or vice-versa? My site addresses a lot of the same subjects as yours and I believe we could greatly benefit from each other. If you are interested feel free to send me an e-mail. I look forward to hearing from you! Wonderful blog by the way!

카지노쿠폰 说:
2024年3月28日 12:22

i hope that it assists because it helps me alot.. ..and occasionally even when i have writers block and i am doing some thing else to take my mind off of my composing, i come across a time when i Wish to create more of my story simply because i guess my writer’s block is cured, so occasionally the correct time comes to you, i guess sometimes all u have to do is wait.. ...i know i dont make sence but try obtaining watever u can from my answer and see if it works!!

안전토토사이트 说:
2024年3月28日 12:22

Considerably, the particular post is truly the greatest with this deserving subject. To be sure together with your results and also can easily thirstily look forward to Your own potential improvements. Simply just declaring thank you will, no doubt not simply just be sufficient, for your wonderful quality within your writing. I will immediately grab your rss to remain up to date with any kind of updates. Real perform as well as much success inside your company dealings!

메이저놀이터 说:
2024年3月28日 12:23

Please tell me that youre going to keep this up! Its so great and so important. I cant wait to read more from you. I just feel like you know so a lot and know how to make people listen to what youve to say. This weblog is just too cool to be missed. Wonderful things, definitely. Please, PLEASE keep it up!

토동산 说:
2024年3月28日 12:32

"The Ultimate Guide to Autumn Adventures: Top 10 Fall Foliage Destinations" - Dive into the heart of autumn's wonder with our expertly chosen destinations, showcasing the most enchanting places to savor the rich, warm colors of fall foliage.

사설토토사이트 说:
2024年3月28日 12:32

"The Ultimate Guide to Autumn Adventures: Top 10 Fall Foliage Destinations" - Dive into the heart of autumn's wonder with our expertly chosen destinations, showcasing the most enchanting places to savor the rich, warm colors of fall foliage.

안전놀이터가입 说:
2024年3月28日 12:32

Can I simply say what a relief to search out each person who virtually is aware of what theyre speaking about at the net. You truly apprehend the manner to carry an problem to mild and make it important. Extra oldsters have to have a look at this and apprehend this side of the story. I cant believe youre now not more popular since you genuinely have the present.

먹튀검증사이트 说:
2024年3月28日 12:40

hi there! Nice stuff, do maintain me published whilst you submit again some thing like this! Extraordinary put up.. Happy i got here throughout this looking forward to proportion this with every body here thank you for sharing . You've got achieved a awesome activity on this article. I've simply stumbled upon your blog and enjoyed analyzing your weblog posts very a good deal. Thank you for the beneficial data. First-rate article with splendid idea! Thanks for any such precious article. I definitely appreciate for this terrific statistics.. I’m extremely impressed together with your writing capabilities and also with the layout on your blog.

먹튀사이트조회 说:
2024年3月28日 12:41

satisfactory article if u searching out real-time a laugh first-rate evening desert safari dubai and incredible tour applications at an inexpensive charge then u contact the enterprise. That is a incredible article thanks for sharing this informative information. I'm able to visit your blog frequently for some modern-day publish. I can visit your weblog often for a few modern put up. Awesome blog. I enjoyed analyzing your articles. That is certainly a exquisite study for me. I have bookmarked it and i am searching forward to reading new articles. Maintain up the best work! Thanks for the valuable information and insights you have so supplied right here..

안전놀이터모음 说:
2024年3月28日 12:42

hiya there. I discovered your blog using msn. That is a very well written article. I’ll make certain to bookmark it and come lower back to examine more of your beneficial data. Thank you for the put up. I’ll absolutely go back. Nice publish. I find out some thing more difficult on awesome blogs everyday. I stumbled onto your weblog and study a few posts. Thank you for shar

먹튀검증 说:
2024年3月28日 12:53

*The next time I read a blog, I hope that it doesnt disappoint me as much as this one. I mean, I know it was my choice to read, but I actually thought youd have something interesting to say. All I hear is a bunch of whining about something that you could fix if you werent too busy looking for attention.

먹튀검증 说:
2024年3月28日 12:54

Really unquie place, Thank you so much meant for posting The experience. Fantasticly penned report, anxieties most of folks given similar volume of material as you may, the online market place might be a a lot better put. Be sure to keep it up!

먹튀검증 说:
2024年3月28日 14:24

Considerably, the particular post is truly the greatest with this deserving subject. To be sure together with your results and also can easily thirstily look forward to Your own potential improvements. Simply just declaring thank you will, no doubt not simply just be sufficient, for your wonderful quality within your writing. I will immediately grab your rss to remain up to date with any kind of updates. Real perform as well as much success inside your company dealings!

먹튀검증 说:
2024年3月28日 14:24

satisfactory article if u searching out real-time a laugh first-rate evening desert safari dubai and incredible tour applications at an inexpensive charge then u contact the enterprise. That is a incredible article thanks for sharing this informative information. I'm able to visit your blog frequently for some modern-day publish. I can visit your weblog often for a few modern put up. Awesome blog. I enjoyed analyzing your articles. That is certainly a exquisite study for me. I have bookmarked it and i am searching forward to reading new articles. Maintain up the best work! Thanks for the valuable information and insights you have so supplied right here..

먹튀사이트 说:
2024年3月28日 14:25

Genuinely like your internet site however you need to check the spelling on quite a few of your posts. A number of them are rife with spelling problems and that i in finding it very bothersome to inform the reality then again i’ll clearly come again once more. Beneficial facts on topics that plenty are involved on for this wonderful submit. Admiring the effort and time you positioned into your b!.. You have got a very excellent format for your blog. I want it to apply on my web page too ,what i don’t understood is in fact how you’re no longer definitely lots more smartly-liked than you may be proper now. You are very smart. You recognise consequently appreciably in terms of this count, produced me for my part believe it from severa various angles. Its like women and men don’t seem to be fascinated till it is something to do with girl gaga! Your person stuffs great. At all times address it up! This was novel. I wish i may want to read each post, however i ought to move back to paintings now… however i’ll return. Very first-rate publish, i simply love this internet site, preserve on it

퍼스트카지노 说:
2024年3月28日 15:23

Genuinely like your internet site however you need to check the spelling on quite a few of your posts. A number of them are rife with spelling problems and that i in finding it very bothersome to inform the reality then again i’ll clearly come again once more. Beneficial facts on topics that plenty are involved on for this wonderful submit. Admiring the effort and time you positioned into your b!.. You have got a very excellent format for your blog. I want it to apply on my web page too ,what i don’t understood is in fact how you’re no longer definitely lots more smartly-liked than you may be proper now. You are very smart. You recognise consequently appreciably in terms of this count, produced me for my part believe it from severa various angles. Its like women and men don’t seem to be fascinated till it is something to do with girl gaga! Your person stuffs great. At all times address it up! This was novel. I wish i may want to read each post, however i ought to move back to paintings now… however i’ll return. Very first-rate publish, i simply love this internet site, preserve on it

먹튀검증 说:
2024年3月28日 15:23

Investigate the potential of algorithmic stablecoin arbitrage methods, as stablecoins are a critical part of the cryptocurrency ecosystem and their prices can differ across different exchanges.

사설토토 说:
2024年3月28日 15:24

i found your internet site internet website online on line and check more than one your early posts. Always hold in the tremendous function. I just additional your rss to my msn news reader. Looking for forward to reading a long way more from you finding out down the street!… dude.. I am not a whole lot into reading, but somehow i got to examine many articles for your weblog. Its extraordinary how interesting it's far for me to stop via you quite often. Just looking round some blogs, appears a quite first-rate platform you are using and the theme as properly. I’m currently the usage of wordpress for some of my web sites however looking to exchange one of them over to a platform much like yours as a trial run. Whatever especially you will suggest about it? This is certainly exciting, you're a totally skilled blogger. I have joined your feed and stay up for trying to find more of your extraordinary put up. Moreover, i’ve shared your internet web page in my social networks! An captivating discussion is value remark.

사설먹튀검증 说:
2024年3月28日 16:04

Please tell me that youre going to keep this up! Its so great and so important. I cant wait to read more from you. I just feel like you know so a lot and know how to make people listen to what youve to say. This weblog is just too cool to be missed. Wonderful things, definitely. Please, PLEASE keep it up!

토토사이트 说:
2024年3月28日 16:04

Please tell me that youre going to keep this up! Its so great and so important. I cant wait to read more from you. I just feel like you know so a lot and know how to make people listen to what youve to say. This weblog is just too cool to be missed. Wonderful things, definitely. Please, PLEASE keep it up!

토토디펜드 说:
2024年3月28日 16:04

My wife and i got so thrilled that Albert could do his researching via the precious recommendations he had out of your blog. It is now and again perplexing just to always be making a gift of techniques that many the others could have been selling. And we all fully grasp we need the writer to give thanks to for that. All of the explanations you’ve made, the simple blog navigation, the friendships you aid to foster – it’s got everything spectacular, and it’s helping our son in addition to the family know that that subject is satisfying, which is certainly extremely fundamental. Thanks for everything!

카지노세상 说:
2024年3月28日 16:41

Can I just now say what a relief to find one who in fact knows what theyre speaking about online. You definitely understand how to bring a problem to light making it essential. Workout . should see this and understand this side from the story. I cant think youre less well-known when you absolutely provide the gift.

온라인카지노순위 说:
2024年3月28日 16:41

I have been meaning to read this and just never obtained a chance. It’s an issue that I’m really interested in, I just started reading and I’m glad I did. You’re a fantastic blogger, one of the best that I’ve seen. This weblog undoubtedly has some facts on topic that I just wasn’t aware of. Thanks for bringing this stuff to light.

안전토토사이트 说:
2024年3月28日 16:41

Really unquie place, Thank you so much meant for posting The experience. Fantasticly penned report, anxieties most of folks given similar volume of material as you may, the online market place might be a a lot better put. Be sure to keep it up!

토토사이트 说:
2024年3月28日 16:42

Really unquie place, Thank you so much meant for posting The experience. Fantasticly penned report, anxieties most of folks given similar volume of material as you may, the online market place might be a a lot better put. Be sure to keep it up!

บาคาร่าออนไลน์ 说:
2024年3月28日 16:42

Seriously sturdy, magnificent, fact-filled information and facts listed here. A person's discussions Never need disappoint, and the unquestionably is valid listed here in addition. You actually continually make a fun learn. Do you convey to I'm just happy?: )#) Keep up to date the nice reports.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter