类已继承抽象类时避免重复实现方法:Android版本兼容调度咨询
Great question! When you're stuck with a class that already inherits an abstract class (like your Plugin.java) and need to handle API-specific logic (JobScheduler for ≥21 vs AlarmManager for <21) without duplicating code or cluttering your main class, here are three solid, maintainable approaches:
1. Use the Strategy Pattern (Cleanest for Scalable Logic)
This approach separates your scheduling logic into dedicated strategy classes, so your Plugin only handles selecting the right strategy based on API level—no messy implementation details in your main class.
Step 1: Define a common interface for schedulers
First, create an interface that both scheduling implementations will adhere to:
public interface Scheduler { void scheduleOldEntryDeletion(Context context); }
Step 2: Implement API-specific strategies
Build separate classes for each scheduling mechanism:
// JobScheduler implementation for API ≥21 public class JobSchedulerStrategy implements Scheduler { @Override public void scheduleOldEntryDeletion(Context context) { // Your existing scheduleDeleteJobScheduler() logic here JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo jobInfo = new JobInfo.Builder( 1, // Unique job ID new ComponentName(context, ScheduleDeleteService.class) ) .setPeriodic(86400000) // Example: Run daily .build(); jobScheduler.schedule(jobInfo); } } // AlarmManager implementation for API <21 public class AlarmManagerStrategy implements Scheduler { @Override public void scheduleOldEntryDeletion(Context context) { // Your existing scheduleDeleteAlarmManager() logic here AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, YourAlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT ); alarmManager.setRepeating( AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 86400000, // Example: Repeat daily pendingIntent ); } }
Step 3: Use the strategy in your Plugin class
Now your Plugin can pick the right strategy and call the unified method:
@Override public void onCreate() { super.onCreate(); Context context = getContext(); // Adjust based on your Plugin's context access Scheduler scheduler = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? new JobSchedulerStrategy() : new AlarmManagerStrategy(); scheduler.scheduleOldEntryDeletion(context); }
This keeps your Plugin class lean, follows the Single Responsibility Principle, and makes it easy to modify or add new scheduling strategies later.
2. Wrap Logic in a Static Utility Class (Simpler for Smaller Projects)
If you don't want to add multiple classes, encapsulate all the API-specific logic in a static utility class. Your Plugin just calls a single method:
public class ScheduleUtils { public static void scheduleOldEntryDeletion(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // JobScheduler logic JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo jobInfo = new JobInfo.Builder( 1, new ComponentName(context, ScheduleDeleteService.class) ) .setPeriodic(86400000) .build(); jobScheduler.schedule(jobInfo); } else { // AlarmManager logic AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(context, YourAlarmReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT ); alarmManager.setRepeating( AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 86400000, pendingIntent ); } } }
Then in your Plugin:
@Override public void onCreate() { super.onCreate(); ScheduleUtils.scheduleOldEntryDeletion(getContext()); }
This is a quick, low-boilerplate solution that keeps your Plugin clutter-free.
3. Delegate to a Helper Class (If Your Abstract Class Requires Method Implementations)
If your abstract class mandates that you implement a scheduling method, you can delegate the actual work to one of the strategy classes above instead of writing the logic directly in Plugin:
Suppose your abstract class looks like this:
public abstract class BasePlugin { public abstract void setupScheduling(); }
Your Plugin implementation becomes:
public class Plugin extends BasePlugin { private Context context; @Override public void setupScheduling() { Scheduler scheduler = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? new JobSchedulerStrategy() : new AlarmManagerStrategy(); scheduler.scheduleOldEntryDeletion(context); } }
This way, you fulfill the abstract class's requirements without duplicating or cluttering code.
Final Notes
All these approaches solve your core problem: removing API-specific implementation from your Plugin class (which is already tied to an abstract class) and avoiding duplicate code. The strategy pattern is best for long-term maintainability, while the utility class is great for simpler use cases.
内容的提问来源于stack exchange,提问作者Ricardo Faria

