我正在構建一個用於符號計算的java庫。 我製作了一個抽象表達式類,用於在產品,分數和多項式之間進行各種操作。但是,當我想增加樓層和天花板時,情況變得複雜。我知道我周圍有這樣的圖書館,我想知道是否有一個特定的設計模式要遵循,或者是否有任何資源可以尋找靈感和指導。符號庫設計模式
符號庫設計模式
回答
很可能你正在做的是解析一個「上下文無關語言」(Type-2,根據Chomsky hierarchy)。嘗試閱讀http://en.wikipedia.org/wiki/LL_parser和http://en.wikipedia.org/wiki/Pushdown_automaton - 你不一定要了解背後的數學,但它會給你提供線索。
我同意你的觀點,複合設計模式對錶達式的對象表示非常有用。下面的例子來自我的代碼,它的目的是保持一個表達式,但你可以很容易地修改它來捕捉這個想法。
表達式是根對象。它有後代如CompoundExpression,數字,可變等等
public interface Expression {
/**
* @return a numeric value of the expression
*/
double getValue();
/**
* @return a string representation of the expression
*/
String getExpression();
/**
* @return true if the expression is an atomic expression
*/
boolean isLeaf();
}
CompoundExpression爲作爲其操作數的操作的容器。
public class CompoundExpression implements Expression {
/**
* Creates a compound expression.
* @param operation the specified operation
* @param operands The specified operands. The amount of operands must exactly
* match the arity of the operation.
*/
public CompoundExpression(Operation operation, Expression ... operands) {
super();
this.operands = Arrays.asList(operands);
this.operation = operation;
}
/**
* The expressions which this expression is compound of ;)
*/
final private List<Expression> operands;
/**
* The operation on operands.
*/
final private Operation operation;
/**
* {@inheritDoc}
*/
@Override
public String getExpression() {
return this.operation.compose(this.operands);
}
/**
* {@inheritDoc}
*/
@Override
public double getValue() {
return this.operation.calculate(this.operands);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
....
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
....
}
/**
* {@inheritDoc}
*/
@Override
public boolean isLeaf() {
return false;
}
}
數是葉。你可以實現更多類型的葉子,比如變量。
public class Number implements Expression {
/**
* Creates an atomic expression with the specified value.
* @param value the numeric value
*/
public Number(double value) {
super();
this.value = value;
}
/**
* The numeric value of the number.
*/
private double value;
/**
* {@inheritDoc}
*/
@Override
public String getExpression() {
return String.valueOf(this.value);
}
/**
* {@inheritDoc}
*/
@Override
public double getValue() {
return this.value;
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
....
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
....
}
/**
* {@inheritDoc}
*/
@Override
public boolean isLeaf() {
return true;
}
}
操作保持操作,如加,竇,地板,天花板,......它也可能有必要時實際計算價值的能力。
public interface Operation {
/**
* Returns a numeric value of the operation performed on the given operands.
*
* @param operands the list of operands
* @return a numeric value of the operation
*/
double calculate(List<Expression> operands);
/**
* Returns a string representation of the operation performed on the given operands.
* @param operands operands the list of operands
* @return a string representation of the operation
*/
String compose(List<Expression> operands);
/**
* Returns a string representation of the operator
* @return string representation of the operator
*/
String getOperator();
}
BinaryOperation是所有的二元運算的父母。它不一定需要,但它很方便。
public abstract class BinaryOperation implements Operation {
/**
* {@inheritDoc}
*/
@Override
public String compose(List<Expression> operands) {
assert (operands.size() == 2);
final Expression op1 = operands.get(0);
final Expression op2 = operands.get(1);
final boolean op1Leaf = op1.isLeaf();
final boolean op2Leaf = op2.isLeaf();
final StringBuilder builder = new StringBuilder();
if (!op1Leaf) {
builder.append("(");
}
builder.append(op1.getExpression());
if (!op1Leaf) {
builder.append(")");
}
builder.append(this.getOperator());
if (!op2Leaf) {
builder.append("(");
}
builder.append(op2.getExpression());
if (!op2Leaf) {
builder.append(")");
}
return builder.toString();
}
}
二進制操作的一個例子:
public class PlusOperation extends BinaryOperation {
/**
* {@inheritDoc}
*/
@Override
public double calculate(List<Expression> operands) {
assert (operands.size() == 2);
return operands.get(0).getValue() + operands.get(1).getValue();
}
/**
* {@inheritDoc}
*/
@Override
public String getOperator() {
return "+";
}
}
UnaryOperation是所有的一元操作的父。它不一定需要,但它很方便。
public abstract class UnaryOperation implements Operation {
/**
* {@inheritDoc}
*/
@Override
public String compose(List<Expression> operands) {
assert (operands.size() == 1);
return this.getOperator() + "(" + operands.get(0).getExpression() + ")";
}
}
一個一元操作的一個例子:
public class CosinusOperation extends UnaryOperation {
/**
* {@inheritDoc}
*/
@Override
public double calculate(List<Expression> operands) {
assert (operands.size() == 1);
return Math.cos(operands.get(0).getValue());
}
/**
* {@inheritDoc}
*/
@Override
public String getOperator() {
return "cos";
}
}
如何使用它的全部。您可以「手動」創建這樣的表達式:
Expression exp = new CompoundExpression(
new PlusOperation(),
new CompoundExpression(
new DivisionOperation(),
new CompoundExpression(
new PlusOperation(),
new Number(2),
new Number(3)
),
new Number(4)
),
);
而且你必須使用一個下推自動機:)
感謝您的時間和回答Honza。我會看看所有這些,並提供反饋意見。 –
它看起來像我可以使用的東西。但是,我認爲我沒有時間去完成這個計劃的過渡,但我會保留它作爲未來的參考。 –
- 1. 設計數據庫模式
- 2. 設計符號
- 3. 計劃的數據庫模式設計
- 4. Expression Blend 3設計模式感嘆號
- 5. 設計模式
- 6. 設計模式:
- 7. 設計模式
- 8. 設計模式
- 9. 設計模式
- 10. 設計模式
- 11. 設計模式
- 12. 設計模式?
- 13. 設計模式
- 14. MVC設計模式 - 設計模型
- 15. 使用版本庫設計模式和裝飾器設計模式來進行
- 16. 與存儲庫設計模式交易
- 17. 存儲庫設計模式與Dapper
- 18. 工資表數據庫模式設計
- 19. PHP設計模式工廠,倉庫和...?
- 20. MVC存儲庫模式設計決策
- 21. 存儲庫設計模式指導
- 22. MongoDB數據庫模式設計
- 23. 設計數據庫模式(MySQL)
- 24. SQL數據庫模式設計
- 25. C#類庫 - Singleton設計模式
- 26. MVC模式和數據庫設計
- 27. 在mysql中設計數據庫模式
- 28. 數據庫訪問設計模式
- 29. 數據/數據庫設計模式?
- 30. 設計文檔數據庫模式
哼哼的實現,以創建表達,你到底要求什麼呢? –
隨着我向符號庫添加越來越多的功能,我面臨嚴重的設計問題。一開始我只使用符號產品,例如'a * b',那麼我就有一部分產品是另一種產品。當我想要多項式表達式時,事情就會變得棘手,因爲我無法用多項式來輕鬆定義除法。事情變得越來越複雜,我開始遵循或多或少的複合設計模式。不過,我覺得重新發明輪子,如果有人知道在哪裏可以找到更多信息,這將非常有幫助。 –