Синглтон - лучший подход с точки зрения тестирования. В отличие от статических классов, singleton может реализовывать интерфейсы, и вы можете использовать макетный экземпляр и внедрить их.
В приведенном ниже примере я проиллюстрирую это. Предположим, у вас есть метод isGoodPrice (), который использует метод getPrice (), и вы реализуете getPrice () как метод в одиночном коде.
синглтон, обеспечивающий функциональность getPrice:
public class SupportedVersionSingelton {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
// calculate price logic here
return 0;
}
}
Использование getPrice:
public class Advisor {
public boolean isGoodDeal(){
boolean isGoodDeal = false;
ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
int price = supportedVersion.getPrice();
// logic to determine if price is a good deal.
if(price < 5){
isGoodDeal = true;
}
return isGoodDeal;
}
}
In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it.
public interface ICalculator {
int getPrice();
}
Окончательная реализация Singleton:
public class SupportedVersionSingelton implements ICalculator {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
return 0;
}
// for testing purpose
public static void setInstance(ICalculator mockObject){
if(instance != null ){
instance = mockObject;
}
тестовый класс:
public class TestCalculation {
class SupportedVersionDouble implements ICalculator{
@Override
public int getPrice() {
return 1;
}
}
@Before
public void setUp() throws Exception {
ICalculator supportedVersionDouble = new SupportedVersionDouble();
SupportedVersionSingelton.setInstance(supportedVersionDouble);
}
@Test
public void test() {
Advisor advidor = new Advisor();
boolean isGoodDeal = advidor.isGoodDeal();
Assert.assertEquals(isGoodDeal, true);
}
}
В случае, если мы воспользуемся альтернативой использования статического метода для реализации getPrice (), было сложно смоделировать getPrice (). Вы можете издеваться над статическим электричеством, но не все продукты могут его использовать.
getInstance()
метода каждый раз, когда вы хотите его использовать (хотя, вероятно, в большинстве случаев это не имеет значения ).