2017-05-02 1 views
0

Activation Function를 적용하는 클래스를 만들고 싶습니다. Functions 다른 기능이 정의되는 enum이다모든 솔리드 프라이스에 준하는 클래스의 올바른 버젼

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)))); 
    } 

} 

을 다음과 같이 클래스이다. 지금은 sigmoid 기능 만 있지만 더 추가됩니다.

질문

나는 것은 그것 (더를 위반 한 것 할 수 있음) Open-Closed Principle, OOP의 5 개 SOLID 원칙 중 하나를 위반입니다. 앞으로 더 많은 함수를 추가 할 수 있도록이 클래스를 작성하는 올바른 방법은 무엇입니까?

도움을 주시면 감사하겠습니다.

+3

여기에 솔리드 원칙을 적용 할 수 없습니다. 그것은 대상이 아닙니다. 그것은 국가가 없습니다. 그것은 정적 메서드의 모음입니다. 이것은 OOP가 아니라 절차 적입니다. 공짜로 클래스가 "... 기능"이라고해야합니다. – Michael

답변

2

enum 자체에 공통 인터페이스 구현을 배치 할 수 있습니다. 이 같은

뭔가 :

ActivationFunction 다음 쓰기 매우 간단하게 당신의
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); 
} 

- 그것은 더 이상 아마 도움이 아니에요.

+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처럼, 또 다른 열거 값을 정의, 더 많은 기능을 필요로 할 때마다. 하나 이상의 방법이 필요한 경우 computecompute2 다른 방법을 추가하십시오.

내가 선택한 모든 이름은 바보 같지만 중요한 점을 얻길 바랍니다. 아니면 질문의 목표를 완전히 놓쳤습니까?

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); 
    } 
} 

당신은 새로운 기능에 대한 새로운 클래스를 생성하고 기능 인터페이스를 구현해야합니다

+0

나는이 "디자인 패턴"을 사용하고자하는 단 하나의 이유를 생각할 수 없다. – Michael

+1

@Michael : 왜 그런가? 합리적인 설명? – Harmlezz

+0

1)'compute'는 무의미한 이름입니다 (둘 다 적용하기에 충분히 일반화되어야합니다). 2)이 열거 형은 상태가 없으므로 객체 지향적이지 않습니다. 3) 기본적으로 functor이고 우리는 지금 그것을위한 lambda를 가지고 있습니다. – Michael

0

여기 내 솔루션입니다. 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

관련 문제