在 Android 中使用 Java 进行抽象

Abstraction with Java in Android

我正在学习一些关于 Java 语言的教程。我想知道我是否应该在每次编写代码时以及在任何类型的标准和堆栈上进行抽象?

我已经看到,例如,对于每个 Spring 服务,我们甚至可以抽象控制器,在 JavaEE 堆栈等上使用与 EJB 的接口等。

我想知道这样做的目的是什么?在使用 Android SDK 开发时我应该做同样的事情吗?

我应该对我编码的每个 class 进行抽象吗?

当您有一个您不想实现其所有方法的 class 时,您需要抽象。那些继承它的 classes 将被迫实现所有这些方法,否则你需要将 subclasses 也声明为抽象的。

除了你应该知道接口之外,接口的方法不能有主体,好处是你的 class 可以实现你想要的接口。鉴于,您只能继承一个摘要class。接口就像合同。无论哪个 class 实现它们都需要为它们的所有方法提供主体。

您是否需要抽象或接口或两者都取决于您的设计和您想要实现的内容。尽管强制那些具有通用方法的 classes 实现相同的接口(如果你对每个方法的主体一无所知)或抽象(如果你知道某些方法的主体是什么)是一个很好的做法, 全部或 none 个方法)

另一个例子是当你有抽象或接口时,如果你向它们添加一些东西,所有实现它们的子classes或classes都需要遵循这些修改,这意味着可能会更容易修改。

也看看 this, this and this and open/close principle

制作模块化可重用组件总是一个好主意。当考虑到这一点从头开始构建应用程序时,它会变得越来越 可扩展 ,越来越 可自扩展 。随着新功能的添加,应用程序中的相同组件会被重新使用,从而节省时间和精力。以后进行更改或识别错误来源变得更加容易。重构不应该是事后,而是从头开始。

话虽如此,仅仅为了 "abstraction" 而在移动应用程序中拥有越来越多的抽象并不是一个好主意。原因当然是智能手机没有服务器甚至台式电脑那么强大。 Android 应用程序中的每个 class 和虚拟方法都会带来性能损失。 "abstraction"和效率之间需要有更大的平衡,性能的权衡在中低端设备上变得更加明显。

来自官方文档:

1. Be careful with code abstractions

2. Avoid dependency injection frameworks

3. Avoid Creating Unnecessary Objects

4. Prefer Static Over Virtual

5. Avoid Internal Getters/Setters

编辑:

在最近尝试 Dagger 之后,我不得不承认第 2 点现在可能有点过时了。还能说什么...来Dagger派对挺晚的

这可以用许多不同的方式来解释。在我看来,在需要扩展或多种实现类型的情况下,抽象在编码中用作设计原则。例如,在 Spring 中,控制器可能已定义为抽象 class (A) 并且具有扩展 A 的几种其他类型的控制器(B、C、D..)。作为 Spring 框架,如果您对可用的控制器实现不满意,您仍然可以开发自己的控制器扩展 A。此外 Spring 开发人员也可以在未来的版本中轻松扩展/添加新控制器。

可重用性。放下手!

如果您的class有一个

  • 重复代码
  • 针对不同场景的非重复代码。

然后声明 class 摘要.

是个好主意

将重复的代码放在抽象中class并为将要不同的代码创建抽象方法。

Here is an example.

注册和取消注册任何 BroadcastReceiver

Abstract class

public abstract class BaseReceiverActivity extends AppCompatActivity{

   private BroadCastReceiver receiver;
   private IntentFilter filter;

   public abstract BroadCastReceiver getReceiver();
   public abstract IntentFilter getFilter();

   @Override
   public void onStart(){
       super.onStart();
       configureReceiver()
       registerReceiver(receiver, filter);
   }

   @Override
   public void onStop(){
       super.onPause();
       unregisterReceiver(receiver);
   }

   private void registerMyReceiver(){        
       registerReceiver(receiver, filter);    
   }

   private void configureReceiver(){
        receiver = getReceiver();
        filter   = getFilter();
   }

}

Implementation class:

public class WifiScanner extends BaseReceiverActivity{

   @Override
   public void onCreate(Bundle sis){
        super.onCreate(sis);
        setContentView(R.layout.yourLayout);
   }

   @Override
   public BroadCastReceiver getReceiver(){
        return new YourReceiver();
   }

   @Override
   public IntentFilter getFilter(){
        return IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
   }

}