2017-05-02 15 views
0

我想創建一個類,它將Activation Function應用到一個值。類是如下下面所有SOLID Priciples的類的正確版本

public class ActivationFunction { 

    public static double function(double value, Functions functions) { 
     if(functions.equals(Functions.SIGMOID)) { 
      return sigmoid(value); 
     } 
     return 0f; 
    } 
    public static double derivativeOfFunction(double value, Functions functions) { 
     if(functions.equals(Functions.SIGMOID)) 
      return sigmoidDerivative(value); 

     return 0f; 
    } 

    private static double sigmoid(double value) { 
     return 1/(1 + Math.exp(0 - value)); 
    } 
    private static double sigmoidDerivative(double value) { 
     return (Math.exp(0 - value)/((1 + Math.exp(0 - value)) * (1 + Math.exp(0 - value)))); 
    } 

} 

Functions是其中不同的功能所定義的enum。現在只有sigmoid功能,但會增加更多功能。

問題

我的東西它違反了Open-Closed Principle,OOP的5個SOLID原則之一(可能它違反以上)。那麼,編寫這個類以適應未來更多功能的正確方法是什麼?

任何幫助表示讚賞。

+3

您不能在這裏應用任何SOLID原則。它甚至不是一個對象。它沒有國家。這只是一個靜態方法的集合。這是程序性的,而不是面向對象。一個贈品應該是班級被稱爲「......功能」 – Michael

回答

2

您可以將公共接口的實現放置在枚舉本身中。

事情是這樣的:

public enum Functions { 
    SIGMOID { 
    public double function(double value) { return 1/(1 + Math.exp(0 - value)); } 
    public double derivative(double value) { return ...; } 
    }, 
    OTHER_FUNCTIONS { ... } 

    public abstract double function(double value); 
    public abstract double derivative(double value); 
} 

ActivationFunction就成爲寫得很簡單 - 它甚至可能沒有什麼用處了。

+0

我認爲這將是最好的方式。 –

0

如何給你的enum值這樣的行爲?

enum MyFunctions { 
    FUNC_1 { 
     @Override double compute(double value) { 
      return 1/(1 + Math.exp(0 - value)); 
     } 
    }, 

    FUNC_2 { 
     @Override double compute(double value) { 
      return (Math.exp(0 - value)/((1 + Math.exp(0 - value)) * (1 + Math.exp(0 - value)))); 
     } 
    }; 

    abstract double compute(double value); 
} 

無論何時您需要更多功能,請定義另一個枚舉值,如FUNC_3。如果您需要更多的方法compute添加另一種方法compute2

我選擇的所有名字都很無聊,但我希望你明白這一點。還是我完全錯過了你的問題的目標?

+0

我想不出你會想要使用這種「設計模式」的單一原因 – Michael

+1

@Michael:爲什麼不呢?任何合理的解釋? – Harmlezz

+0

1)'compute'是一個沒有意義的名稱(並且需要足夠通用才能適用於兩者)2)這些枚舉是無狀態的,因此不是面向對象的3)它基本上是一個函子,現在我們有lambda表達式 – Michael

0

這裏是我的解決方案:

public interface Function { 
    double doIt(double value); 
} 

public class Sigmoid implements Function { 
    @Override 
    public double doIt(double value) { 
     return 0; 
    } 
} 

public class ActivationFunction { 
    public static double callFunction(Function function,double value){ 
     return function.doIt(value); 
    } 
} 

您應該創建新的功能,新的類並實現功能接口。 callFunction參數類型Function,因此添加新功能時不需要更改它,並且Open-Closed Principle正確。

+0

這比其他答案要好,但是您已經有效地重新定義了['DoubleUnaryOperator'](https://docs.oracle.com/javase/8/docs/api/java/util/function/DoubleUnaryOperator.html) – Michael

+0

我沒有不知道那個界面。那麼,正確的答案是「使用DoubleUnaryOperator」嗎? –

+0

在我看來,也許是。隨意做一些關於它的閱讀並編輯你的答案! – Michael