एक ऑब्जेक्ट ओरिएंटेड विकल्प को अत्यधिक बड़े switch
और if/else
निर्माणों को बदलने के Chain of Responsibility Pattern
लिए निर्णय लेने के लिए मॉडल का उपयोग करना है।
जिम्मेदारी पैटर्न की श्रृंखला
जिम्मेदारी पैटर्न की श्रृंखला एक अनुरोध के स्रोत को अलग करने की अनुमति देती है, जो यह तय करती है कि अनुरोध के लिए संभावित बड़ी संख्या में हैंडलर को क्या कार्रवाई करनी चाहिए। श्रृंखला की भूमिका का प्रतिनिधित्व करने वाला वर्ग हैंडलर की सूची के स्रोत से अनुरोधों को तब तक प्रसारित करता है जब तक कि कोई हैंडलर अनुरोध को स्वीकार नहीं करता है और इसे कार्रवाई करता है।
यहां एक उदाहरण कार्यान्वयन है जो कि जेनरिक का उपयोग करके टाइप सेफ भी है।
import java.util.ArrayList;
import java.util.List;
/**
* Generic enabled Object Oriented Switch/Case construct
* @param <T> type to switch on
*/
public class Switch<T extends Comparable<T>>
{
private final List<Case<T>> cases;
public Switch()
{
this.cases = new ArrayList<Case<T>>();
}
/**
* Register the Cases with the Switch
* @param c case to register
*/
public void register(final Case<T> c) { this.cases.add(c); }
/**
* Run the switch logic on some input
* @param type input to Switch on
*/
public void evaluate(final T type)
{
for (final Case<T> c : this.cases)
{
if (c.of(type)) { break; }
}
}
/**
* Generic Case condition
* @param <T> type to accept
*/
public static interface Case<T extends Comparable<T>>
{
public boolean of(final T type);
}
public static abstract class AbstractCase<T extends Comparable<T>> implements Case<T>
{
protected final boolean breakOnCompletion;
protected AbstractCase()
{
this(true);
}
protected AbstractCase(final boolean breakOnCompletion)
{
this.breakOnCompletion = breakOnCompletion;
}
}
/**
* Example of standard "equals" case condition
* @param <T> type to accept
*/
public static abstract class EqualsCase<T extends Comparable<T>> extends AbstractCase<T>
{
private final T type;
public EqualsCase(final T type)
{
super();
this.type = type;
}
public EqualsCase(final T type, final boolean breakOnCompletion)
{
super(breakOnCompletion);
this.type = type;
}
}
/**
* Concrete example of an advanced Case conditional to match a Range of values
* @param <T> type of input
*/
public static abstract class InRangeCase<T extends Comparable<T>> extends AbstractCase<T>
{
private final static int GREATER_THAN = 1;
private final static int EQUALS = 0;
private final static int LESS_THAN = -1;
protected final T start;
protected final T end;
public InRangeCase(final T start, final T end)
{
this.start = start;
this.end = end;
}
public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
{
super(breakOnCompletion);
this.start = start;
this.end = end;
}
private boolean inRange(final T type)
{
return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
(type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
}
}
/**
* Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
*
* @param args command line arguments aren't used in this example
*/
public static void main(final String[] args)
{
final Switch<Integer> integerSwitch = new Switch<Integer>();
final Case<Integer> case1 = new EqualsCase<Integer>(1)
{
@Override
public boolean of(final Integer type)
{
if (super.type.equals(type))
{
System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
return super.breakOnCompletion;
}
else
{
return false;
}
}
};
integerSwitch.register(case1);
// more instances for each matching pattern, granted this will get verbose with lots of options but is just
// and example of how to do standard "switch/case" logic with this pattern.
integerSwitch.evaluate(0);
integerSwitch.evaluate(1);
integerSwitch.evaluate(2);
final Switch<Integer> inRangeCaseSwitch = new Switch<Integer>();
final Case<Integer> rangeCase = new InRangeCase<Integer>(5, 100)
{
@Override
public boolean of(final Integer type)
{
if (super.inRange(type))
{
System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
return super.breakOnCompletion;
}
else
{
return false;
}
}
};
inRangeCaseSwitch.register(rangeCase);
// run some examples
inRangeCaseSwitch.evaluate(0);
inRangeCaseSwitch.evaluate(10);
inRangeCaseSwitch.evaluate(200);
// combining both types of Case implementations
integerSwitch.register(rangeCase);
integerSwitch.evaluate(1);
integerSwitch.evaluate(10);
}
}
यह सिर्फ एक त्वरित पुआल आदमी है जिसे मैंने कुछ मिनटों में मार दिया था, एक अधिक परिष्कृत कार्यान्वयन कुछ प्रकार के कार्यान्वयन के लिए अनुमति दे सकता है इसे कॉल बैक आईओसी शैली के अधिक बनाने के लिए कार्यान्वयन के उदाहरणों Command Pattern
में इंजेक्ट किया जा सकता Case
है।
एक बार इस दृष्टिकोण के बारे में अच्छी बात यह है कि स्विच / केस स्टेटमेंट्स सभी साइड इफेक्ट्स के बारे में हैं, यह क्लासेस में साइड इफेक्ट्स को इनकैप्सुलेट करता है ताकि उन्हें प्रबंधित किया जा सके, और इसे बेहतर तरीके से इस्तेमाल किया जा सके, यह एक कार्यात्मक भाषा में पैटर्न मैचिंग की तरह अधिक समाप्त होता है यह कोई बुरी बात नहीं है।
मैं इस Gist को Github पर कोई भी अपडेट या एन्हांसमेंट पोस्ट करूंगा ।