다른 경우에는 좋지 않은 경우 이외에 Java에서 스위치 케이스를 구현하는 대체 방법이 있습니까? 선택 사항에 따라 값 집합이 결합되어 실행됩니다.Java의 스위치 케이스에 대한 대안
답변
아마도 상수의 요구 사항에 어려움을 겪고있을 것입니다. 일반적으로이 코드는 냄새지만, 할 수있는 일이 있습니다. 전환하려는 이유를 자세히 설명한 다른 질문을 제기하고 연결할 수도 있습니다. 위의 예에서
Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());
String key = "something";
if (map.contains(key)) {
Object o = map.get(key);
}
, 당신은이 모든 조회로 전환하게
interface Handler {
public void doSomething();
}
처럼, '핸들러'에 뭔가를 매핑 할 수 있습니다.
if (map.contains(key)) { map.get(key).doSomething(); }
다시 말하지만 약간의 냄새가 나기 때문에 추론을 설명하는 질문을 게시하십시오.
public interface Task<T>
{
public void doSomething(T context);
}
public Class SwitchCase<T>
{
Map<Integer,Task<T>> tasks;
Task<T> defaultTask;
public void choose(int choice, T context)
{
Task<T> t= this.tasks.get(choice);
if(t!=null) { t.doSomething(context); return;}
if(defaultTask!=null) { defaultTask.doSomething(context);}
}
}
정수가 고통이라면 열거 형을 사용할 수도 있습니다. – Ibrahim
이와 비슷한 것을 찾고 있습니다. –
왜 포함하고지도에서 두 번 읽는가. 명령 설명 = map.get (key); if (null! = command) { ... command.execute(); } –
무엇을 하시겠습니까? 왜 Switch-Case가 충분하지 않습니까?
빠른 답은 경우 - 다른
if() {}
else if() {}
...
else if() {}
를 사용할 수 있습니까?
는하지만 ...
if,else if,else
의 추악한 시리즈가 더 언급하지 않았다?
if
(else if
및 else
과 함께) 문장은 어떻습니까? switch
은 정수 또는 열거 유형에 대해 동등성을 사용하여 전환 만 허용하지만 if
을 사용하면 부울 논리를 사용할 수 있습니다.
char, byte, short도 스위치에 사용할 수 있습니다. – dogbane
예, 안전하게 (자동) int로 캐스팅 할 수도 있습니다 –
코드를 리팩토링하여 다형성을 사용하면 switch 문이 필요하지 않을 수 있습니다. 그러나 스위치에 대한 합법적 인 사용법이 있으므로 상황에 따라 다릅니다.
예 - 이것은 잘 알려진 리팩토링입니다. http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html – RichardOD
좋은 링크. 카탈로그에 좋은 것들이 많이있는 것처럼 보입니다. –
언제든지 스위치를 if-else if-else if-else if...
으로 바꿀 수는 있지만 원하는 이유는 없습니다. 문맥에 따라 switch
또한 때로는 배열이나 해시 맵으로 대체 될 수 있습니다.
코드 주위에 스위치/사례 설명이 많아서 당신을 미치게 만듭니다.
당신은 리팩토링을 선택할 수 있습니다 : Replace conditional with polymorphism.
의 당신이 다른 장치에 정보를 저장하는 데 사용되는 소프트웨어의 조각 있다고 가정 해 봅시다 : 4 개 지속성 작업이 정의됩니다 삭제, 가져 오기 저장을, 업데이트은 N 개의 지속성 메커니즘 (플랫 파일, 네트워크, RDBMS, XML 등)으로 구현 될 수 있습니다.
class YourProblematicClass {
....
public void fetchData(Object criteria) {
switch (this.persitanceType) {
case FilePersistance:
// open file
// read it
// find the criteria
// build the data
// close it.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// retrieve the data
// build the data
// close connection
break();
case DataBasePersistace:
// Get a jdbc connection
// create the query
// execute the query
// fetch and build data
// close connection
break;
}
return data;
}
업데이트/삭제/
public void saveData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
// open file, go to EOF, write etc.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// etc
break();
case DataBasePersistace:
// Get a jdbc connection, query, execute...
break;
}
}
을 저장 동일 그리고 전 :
코드는 당신이 이것을 가지고 4 개 개의 다른 장소에서 그래서 그들 모두를 지원해야 등등 ....
public void deleteData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
public void updateData(Object data) {
switch (this.persitanceType) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
스위치/case 문을 사용하여 6,
는 문제가된다 :
때마다 당신이 각 섹션에서 새로운 스위치/케이스를 삽입해야 새로운 유형을 추가하고 싶습니다.
여러 번, 몇 가지 유형이 유사하며, 그들은
- 그들이 어떤 다른 (당신이 그들을 단계적으로 수), 그리고 몇 번 그들이 당신은 할 수있다
- 다소 차이가 다른 스위치/케이스 필요하지 않습니다 심지어 플러그인과 같은 런타임에 다른 유형을로드해야 할 필요가 있습니다.
리팩토링은 인터페이스 또는 추상 유형을 추가하고 다른 유형이 해당 인터페이스를 구현하고 해당 객체에 책임을 위임하는 것입니다. 그들의 논리에 따라 구현하는 것이
public interface PersistenceManager {
public void fetchData(Object criteria);
public void saveData(Object toSave);
public void deleteData(Object toDelete);
public void updateData(Object toUpdate);
}
후 다른 구현
public class FilePersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// open file
// read it
// find the criteria
// build the data
// close it.
}
public void saveData(Object toSave) {
// open file, go to EOF etc.
}
public void deleteData(Object toDelete){
....
}
public void updateData(Object toUpdate){
....
}
}
그리고 다른 유형 :
그래서 당신이 뭔가를 할 것입니다. 네트워크는 소켓과 스트림을 처리 할 것이고, DB는 노드 등을 사용하여 JDBC, ResultSets 등 XML을 처리 할 것이다.
public class NetworkPersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// Socket stuff
}
public void saveData(Object toSave) {
// Socket stuff
}
public void deleteData(Object toDelete){
// Socket stuff
}
public void updateData(Object toUpdate){
// Socket stuff
}
}
public class DataBasePersistence implements PersistanceManager {
public void fetchData(Object criteria) {
// JDBC stuff
}
public void saveData(Object toSave) {
// JDBC stuff
}
public void deleteData(Object toDelete){
// JDBC stuff
}
public void updateData(Object toUpdate){
// JDBC stuff
}
}
마지막으로 호출을 위임 받아야합니다.
나중에
:public YouProblematicClass { // not longer that problematic
PersistamceManager persistance = // initialize with the right one.
public void fetchData(Object criteria) {
// remove the switch and replace it with:
this.persistance.fetchData(criteria);
}
public void saveData(Object toSave) {
// switch removed
this.persistance.saveData( toSave);
}
public void deleteData(Object toDelete){
this.persistance.deleteData(toDelete);
}
public void updateData(Object toUpdate){
this.persistance.updateData(toUpdate);
}
}
그래서, 당신은 단지 한 번만 유형에 따라 지속성 관리자에 대한 올바른 인스턴스를 만들어야합니다. 그런 다음 모든 호출은 다형성으로 해결됩니다. 이것이 바로 객체 지향 기술의 핵심 기능 중 하나입니다.
다른 지속성 관리자가 필요하다고 결정하면 새 구현을 만들고 클래스에 할당하면됩니다.
public WavePersistance implements PersistanceManager {
public void fetchData(Object criteria) {
// ....
}
public void saveData(Object toSave) {
// ....
}
public void deleteData(Object toDelete){
// ....
}
public void updateData(Object toUpdate){
// ....
}
}
아주 좋은 답변입니다! – mac
또는 1 동적 스위치 케이스의 종류를 상상할 수있다.
그 외 : 스위치 케이스, 다형성 또는 심지어 if/else를 사용하여 "노이즈"를 줄이고 코드를보다 깨끗하게 만들 수 있는지 여부를 결정하는 것이 이치에 맞다고 생각합니다. 사건의 수는 여기에서 중요한 역할을합니다.
내가 "클린 코드"스위치/경우에 따라 멋진 장을 가지고 대/다른 경우 같아요
문자열이 정적 인 경우 ENUM을 만들 수 있습니다. 스위치를 켜십시오.
스위치 케이스를 enum으로 바꾼 전형적인 경우를 게시합니다.
public enum PatternTypes {
ALPHA_CHAR, ALPHANUMERIC_CHAR, ADDITIONAL_CHAR, UNICODE_BMP_CHARS
}
과 기능 :
public enum PatternTypes {
/**
* RegEx patterns divided by restriction level
*/
ALPHA_CHAR("[a-zA-Z]+"),
ALPHANUMERIC_CHAR("[a-zA-Z0-9\\_]+"),
ADDITIONAL_CHAR("[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~]+"),
UNICODE_BMP_CHARS("[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~\u00A0-\uD7FF\uF900-\uFFFD]+");
public String getPatternContent() {
return patternContent;
}
private String patternContent;
PatternTypes(String patternContent) {
this.patternContent = patternContent;
}
}
: 리팩토링 PatternTypes
후
private static final String ALPHA_CHAR = "[a-zA-Z]+";
private static final String ALPHANUMERIC_CHAR = "[a-zA-Z0-9\\_]+";
private static final String ADDITIONAL_CHAR = "[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~]+";
private static final String UNICODE_BMP_CHARS = "[a-zA-Z0-9\\_\\-\\,\\.\\s\\!\\#\\$\\&\\(\\)\\*\\+\\;\\:\\=\\?\\@\\|\\[\\]\\{\\}\\~\u00A0-\uD7FF\uF900-\uFFFD]+";
/*
* Match given classAbbr with given RegEx pattern
*/
private void checkInvalidClassAbbr(String classAbbr,
PatternTypes classAbbrPattern) {
switch (classAbbrPattern) {
case ALPHA_CHAR:
checkUnmatched(classAbbr, ALPHA_CHAR, CLASS_ABBR_VAR_NAME);
break;
case ALPHANUMERIC_CHAR:
checkUnmatched(classAbbr, ALPHANUMERIC_CHAR, CLASS_ABBR_VAR_NAME);
break;
case ADDITIONAL_CHAR:
throw new MalFormedDNException("Not support Pattern Type:"
+ classAbbrPattern);
case UNICODE_BMP_CHARS:
throw new MalFormedDNException("Not support Pattern Type:"
+ classAbbrPattern);
}
}
가 수정 리팩터링 전에
나는 열거PatternTypes
이 기능은 다음과 같이 단순화됩니다.
/*
* Match given classAbbr with given RegEx pattern
*/
private void checkInvalidClassAbbr(String classAbbr, PatternTypes classAbbrPattern) {
if (PatternTypes.ADDITIONAL_CHAR.equals(classAbbrPattern) || PatternTypes.UNICODE_BMP_CHARS.equals(classAbbrPattern)){
throw new MalFormedDNException("RegEx pattern:" + classAbbrPattern.name() + "is not allowed for Class Abbr");
}
checkUnmatched(classAbbr, classAbbrPattern.getPatternContent(), CLASS_ABBR_VAR_NAME);
}
해시 맵은 메모리 사용이 불가능한 것으로 간주되므로이 용도로 열거 형을 사용할 수 있습니다.
예 :
class EnumExample4{
enum Season{
WINTER(5), SPRING(10), SUMMER(15), FALL(20);
private int value;
private Season(int value){
this.value=value;
}
}
public static void main(String args[]){
System.out.println(Season.WINTER.value); //This gives you 5
}}
이 스위치 케이스를 작성 또는 진술 여부를 SVE 것입니다.
클레임을 뒷받침 할 수있는 참고 자료를 몇 개 주시겠습니까? * 해시 맵은 메모리 친화적 인 것으로 간주되지 않습니다 *. 가능한 경우 답변을 수정하여 거기에 링크하십시오. – derM
'한 세트의 값이 콤보로 표시됩니다'라고 할 때 무엇을 의미합니까? – Alterlife
이미 비슷한 질문이 있습니다. http://stackoverflow.com/questions/126409/ways-to-eliminate-switch-in-code –
@cdb : 왜 다시 부탁 했습니까? 이전 답변에서 알려주지 않은 내용은 무엇입니까? –