當我有一些算法,它可以根據分立元件(如令牌,動作等),改變自己的行爲,你可以看到如果State design pattern可能是一個很好的匹配。
與其他方法相比,該模式有點冗長,但如果需要可以非常容易地擴展。我們先從一個抽象狀態類:它的目標是讓你從一個狀態改變到另一個時,一個新的令牌發揮作用:
public abstract class State
{
public static string[] operators = new string[] { "+", "-", "*", "/" };
public List<string> Expressions { get; set; }
public List<string> Tokens { get; set; }
public abstract State Process(string token);
}
,我們可以有從這個派生每個狀態;我們可以嘗試對他們前期型號:我們基本上可以描述2案件
- 要麼我們不關心的下一個標記,因爲前面的標識與運營商端(或我們開始我們的第一個表達式)
- 或者我們希望下一個標記到達開始與運營商,如果我們想繼續表達
讓我們創建的第一個狀態:
public class WaitingForAnyTokenState : State
{
public override State Process(string token)
{
return PushTokenToTokenList(token);
}
protected State PushTokenToTokenList(string token)
{
Tokens.Add(token);
if (operators.Any(op => token.EndsWith(op)))
{
return new WaitingForAnyTokenState() { Expressions = Expressions, Tokens = Tokens };
}
return new WaitingForOperationState() { Expressions = Expressions, Tokens = Tokens };
}
}
巴斯cally,我們說如果令牌以操作結束,我們不關心下一個令牌,因爲它會被摺疊到當前表達式中:我們返回WaitingForAnyTokenState
。
相反,如果我們不與操作結束了,會發生什麼情況,以目前的表達依賴於下一個標記。如果它從一個操作開始,表達式會繼續。如果不是,當前表達式結束,我們開始一個新的表達式。
public class WaitingForOperationState : State
{
public override State Process(string token)
{
CloseCurrentExpression(token);
return PushTokenToTokenList(token); // let's imagine the same method as above is accessible here
}
private void CloseCurrentExpression(string token)
{
if (!operators.Any(op => token.StartsWith(op)))
{
CombineTokensIntoExpression();
Tokens = new List<string>();
}
}
}
有趣的是,下一個案件仍然以與第一個國家相同的方式決定。唯一需要改變的是當前表達式的關閉。
這裏是建築的示例代碼,你可以使用:
private static void Main(string[] args)
{
var ttea = new TokenToExpressionAggregator();
foreach (var l in new string[] { "a+", "+1", "+c-", "d", "e", "+d", "z+", "a+" }) {
ttea.Add(l);
}
ttea.EndAggregation();
foreach (var expression in ttea.CurrentState.Expressions) {
Console.WriteLine(expression);
}
}
public class TokenToExpressionAggregator
{
public State CurrentState { get; set; }
public TokenToExpressionAggregator()
{
CurrentState = new InitialState();
}
public void Add(string token)
{
CurrentState = CurrentState.Process(token);
}
public void EndAggregation()
{
CurrentState = new FinalState(CurrentState);
}
}
public abstract class State
{
public static string[] operators = new string[] { "+", "-", "*", "/" };
public List<string> Expressions { get; set; }
public List<string> Tokens { get; set; }
public abstract State Process(string token);
protected State PushTokenToTokenList(string token)
{
Tokens.Add(token);
if (operators.Any(op => token.EndsWith(op)))
{
return new WaitingForAnyTokenState() { Expressions = Expressions, Tokens = Tokens };
}
return new WaitingForOperationState() { Expressions = Expressions, Tokens = Tokens };
}
protected void CombineTokensIntoExpression()
{
Expressions.Add(string.Join(" ", Tokens.ToArray()));
}
}
public class InitialState : WaitingForAnyTokenState
{
public InitialState()
{
Expressions = new List<string>();
Tokens = new List<string>();
}
}
public class WaitingForAnyTokenState : State
{
public override State Process(string token)
{
return PushTokenToTokenList(token);
}
}
public class WaitingForOperationState : State
{
public override State Process(string token)
{
CloseCurrentExpression(token);
return PushTokenToTokenList(token);
}
private void CloseCurrentExpression(string token)
{
if (!operators.Any(op => token.StartsWith(op)))
{
CombineTokensIntoExpression();
Tokens = new List<string>();
}
}
}
public class FinalState : State
{
public FinalState(State state)
{
Expressions = state.Expressions;
Tokens = state.Tokens;
CombineTokensIntoExpression();
Tokens = null;
}
public override State Process(string token)
{
return this;
}
}
它使冗長,但雄辯的代碼;個人品味和職業環境可能會抗議。但我發現它有助於表達你的狀態之間的功能轉換。由於每個州都很小,並且不依賴於以前的狀態,因此它也更容易測試。我已經採取了一些自由猜測在你的過程中的一些不清楚的地方(是連接運營商無效?),它不是完整的(沒有括號),但我認爲這種結構可以幫助你的那種標記流你似乎有。
究竟爲什麼需要「有效信號」?對我來說,看起來好像在第一關中空間可以被消除;此外,'-'的模糊性顯然不能被消除,這兩種情況都不得不考慮。 – Codor 2014-08-27 11:55:36
元素是否總是一個字母?也許你可以「把所有的值放在一個列表中,刪除空格,在相鄰的字母之間插入逗號」。所以'[ 「一」, 「+ B」, 「C」]''成爲 「A + BC」',它變成' 「A + B,C」' – Kevin 2014-08-27 12:00:13
@Codor ... THX ..也許是我的天堂」非常清楚地闡明瞭它。該空間有效地表示數組元素,並且我需要知道使用哪些元素來訪問有關表達式的其他信息。所以只是連接成一個字符串,然後解析和檢查表達式樹並不能給我所需要的信息 – 2014-08-27 12:02:15