如何创建一个;“可覆盖”;java中的配置?

如何创建一个;“可覆盖”;java中的配置?,java,android,overriding,Java,Android,Overriding,我有两个基于公共代码库项目的应用程序版本 库使用一些常量值来确定一些运行时配置,现在我希望每个应用程序都有一个稍微不同的配置 简化问题:我的库项目中有一个布尔字段,用于确定我是否在应用程序中显示广告。默认情况下,这是真的(如库项目中定义的),应用程序版本A对此没有问题。但我需要应用程序版本B是免费添加的,所以我需要将该值设置为false 如何实现这一点,以便从引用库的项目中基本上重写库项目中的配置值 我可以更改库实现和引用项目的实现 编辑 此外,配置布尔值仅影响库代码的行为。只需将变量封装在ge

我有两个基于公共代码库项目的应用程序版本

库使用一些常量值来确定一些运行时配置,现在我希望每个应用程序都有一个稍微不同的配置

简化问题:我的库项目中有一个布尔字段,用于确定我是否在应用程序中显示广告。默认情况下,这是真的(如库项目中定义的),应用程序版本A对此没有问题。但我需要应用程序版本B是免费添加的,所以我需要将该值设置为false

如何实现这一点,以便从引用库的项目中基本上重写库项目中的配置值

我可以更改库实现和引用项目的实现

编辑


此外,配置布尔值仅影响库代码的行为。

只需将变量封装在getter函数(getFoo())中,并通过代码使用它。然后重写子类中的getter。

只需将变量封装在getter函数(getFoo())中,并通过代码使用它。然后重写子类中的getter。

在这种情况下不应该使用常量值。您应该做的是创建一个包含getter的抽象类,然后像这样扩展该接口:

public abstract class Config {
     public abstract int getValue();
}

public class AppA extends Config {
     private static final int value = 1;

     @Override
     public int getValue(){
         return value;
     }
}

public class AppB extends Config {
     private static final int value = 2;

     @Override
     public int getValue(){
         return value;
     }
}

编辑:OP补充说他需要库代码中的配置值。我建议仍然使用此代码,但在库代码中添加setter,以在应用程序设置代码中获取此getter返回的值。

在这种情况下不应使用常量值。您应该做的是创建一个包含getter的抽象类,然后像这样扩展该接口:

public abstract class Config {
     public abstract int getValue();
}

public class AppA extends Config {
     private static final int value = 1;

     @Override
     public int getValue(){
         return value;
     }
}

public class AppB extends Config {
     private static final int value = 2;

     @Override
     public int getValue(){
         return value;
     }
}

编辑:OP补充说他需要库代码中的配置值。我建议仍然使用此代码,但在库代码中添加setter,以在应用程序设置代码中获取此getter返回的值。

其他选项包括从上下文中获取Android软件包名称,并基于此做出决定,或者从您的清单中提取一段元数据。

其他选项包括从您的上下文中获取Android软件包名称并据此做出决定,或者从您的清单中提取一段元数据。

有点晚了,但我发现此解决方案在我的项目中运行良好。它使用Android
应用程序
类设置覆盖库配置的单例配置实例

public final class Config {

    public static final boolean VAL;

    private Config() {}

    static {
        // this will be overridden by previous calls to 
        // ConfigInstance.getInstance()
        final ConfigInstance confInstance = ConfigInstance.getInstance(ConfigInstance.DEFAULT_VAL);
        VAL = confInstance.val;
   }

}

// Singleton helper class, be sure not to reference the Config class 
// here so that it is not loaded
public final class ConfigInstance {

    private static volatile ConfigInstance instance = null;

    static final boolean DEFAULT_VAL = false;

    public final boolean val;

    private ConfigInstance(final boolean val) {
        this.val = val;
    }

    // thread safe singleton generator
    public static ConfigInstance getInstance(final boolean val) {
        ConfigInstance result = instance;
        if (result == null) {          // 1st check no lock
            synchronized (ConfigInstance.class) {
                result = instance;
                if (result == null) {  // 2nd check with lock
                    instance = result = new ConfigInstance(val);
                }
            }
        }
        return result;
    }

}
public class ApplicationWrapper extends Application {

    static {
        // this will set the singleton ConfigInstance first, ie. before
        // the library static block is executed; forcing it to use the 
        // values here
        ConfigInstance.getInstance(true);
   }

}
下面的
Config
ConfigInstance
在库中

public final class Config {

    public static final boolean VAL;

    private Config() {}

    static {
        // this will be overridden by previous calls to 
        // ConfigInstance.getInstance()
        final ConfigInstance confInstance = ConfigInstance.getInstance(ConfigInstance.DEFAULT_VAL);
        VAL = confInstance.val;
   }

}

// Singleton helper class, be sure not to reference the Config class 
// here so that it is not loaded
public final class ConfigInstance {

    private static volatile ConfigInstance instance = null;

    static final boolean DEFAULT_VAL = false;

    public final boolean val;

    private ConfigInstance(final boolean val) {
        this.val = val;
    }

    // thread safe singleton generator
    public static ConfigInstance getInstance(final boolean val) {
        ConfigInstance result = instance;
        if (result == null) {          // 1st check no lock
            synchronized (ConfigInstance.class) {
                result = instance;
                if (result == null) {  // 2nd check with lock
                    instance = result = new ConfigInstance(val);
                }
            }
        }
        return result;
    }

}
将以下类添加到每个更高级别的项目中,确保在清单中的
标记中设置“name”字段

public class ApplicationWrapper extends Application {

    static {
        // this will set the singleton ConfigInstance first, ie. before
        // the library static block is executed; forcing it to use the 
        // values here
        ConfigInstance.getInstance(true);
   }

}

有了它,
Config.VAL
将在项目中设置为
true

有点晚了,但我发现这个解决方案在我的项目中效果很好。它使用Android
应用程序
类设置覆盖库配置的单例配置实例

public final class Config {

    public static final boolean VAL;

    private Config() {}

    static {
        // this will be overridden by previous calls to 
        // ConfigInstance.getInstance()
        final ConfigInstance confInstance = ConfigInstance.getInstance(ConfigInstance.DEFAULT_VAL);
        VAL = confInstance.val;
   }

}

// Singleton helper class, be sure not to reference the Config class 
// here so that it is not loaded
public final class ConfigInstance {

    private static volatile ConfigInstance instance = null;

    static final boolean DEFAULT_VAL = false;

    public final boolean val;

    private ConfigInstance(final boolean val) {
        this.val = val;
    }

    // thread safe singleton generator
    public static ConfigInstance getInstance(final boolean val) {
        ConfigInstance result = instance;
        if (result == null) {          // 1st check no lock
            synchronized (ConfigInstance.class) {
                result = instance;
                if (result == null) {  // 2nd check with lock
                    instance = result = new ConfigInstance(val);
                }
            }
        }
        return result;
    }

}
下面的
Config
ConfigInstance
在库中

public final class Config {

    public static final boolean VAL;

    private Config() {}

    static {
        // this will be overridden by previous calls to 
        // ConfigInstance.getInstance()
        final ConfigInstance confInstance = ConfigInstance.getInstance(ConfigInstance.DEFAULT_VAL);
        VAL = confInstance.val;
   }

}

// Singleton helper class, be sure not to reference the Config class 
// here so that it is not loaded
public final class ConfigInstance {

    private static volatile ConfigInstance instance = null;

    static final boolean DEFAULT_VAL = false;

    public final boolean val;

    private ConfigInstance(final boolean val) {
        this.val = val;
    }

    // thread safe singleton generator
    public static ConfigInstance getInstance(final boolean val) {
        ConfigInstance result = instance;
        if (result == null) {          // 1st check no lock
            synchronized (ConfigInstance.class) {
                result = instance;
                if (result == null) {  // 2nd check with lock
                    instance = result = new ConfigInstance(val);
                }
            }
        }
        return result;
    }

}
将以下类添加到每个更高级别的项目中,确保在清单中的
标记中设置“name”字段

public class ApplicationWrapper extends Application {

    static {
        // this will set the singleton ConfigInstance first, ie. before
        // the library static block is executed; forcing it to use the 
        // values here
        ConfigInstance.getInstance(true);
   }

}


使用此选项,
Config.VAL
将在项目中设置为
true

您可以私有化布尔引用,并根据需要添加一个返回true/false的公共方法。应用程序版本B可以重写以返回false。如果它不是常量,请不要将其称为常量。它听起来更像一个配置(有很多方法可以创建/使用配置)。@Swati,我想到了,但是库代码需要布尔值,所以它永远不会看到覆盖。但是你不能在库代码中更改实现吗?@Swati如果我实现一个名为“Config”的库类来包装布尔值,然后,我的库代码将调用'Config.getFoo()'来检查布尔值。因此,如果我将Config子类化以获取ConfigVerB,那么我的库代码仍在调用Config.getFoo(),而我的重写什么也不做。您可以私有化布尔引用,并添加一个公共方法,该方法根据需要返回true/false。应用程序版本B可以重写以返回false。如果它不是常量,请不要将其称为常量。它听起来更像一个配置(有很多方法可以创建/使用配置)。@Swati,我想到了,但是库代码需要布尔值,所以它永远不会看到覆盖。但是你不能在库代码中更改实现吗?@Swati如果我实现一个名为“Config”的库类来包装布尔值,然后,我的库代码将调用'Config.getFoo()'来检查布尔值。因此,如果我将Config子类化以获取ConfigVerB,那么我的库代码仍在调用Config.getFoo(),而我的重写什么也不做。我想到了这一点,但库代码需要Config变量,而不是特定于版本的代码。图书馆不会知道新的子类,在我写答案的时候也不知道。在这种情况下,您需要实现我的答案,然后通过函数参数将值传递回库中。图书馆不会知道新的子类,在我写答案的时候也不知道。在这种情况下,您需要实现我的答案,然后通过函数参数将值传递回库中。如果AppA代码和AppB代码需要不同的值,这是正确的方法。但是我需要以库代码可见的方式更改现有库代码的值。如果AppA代码和AppB代码需要不同的值,这是正确的方法。但我需要现有库代码的值以库代码可见的方式进行更改。+1不能回答我的直接问题,但可能是我最终要做的