用组合代替继承能为 Activity 带来什么

用组合代替继承能为 Activity 带来什么


事实上我们在很多 Java 进阶书籍上看到过“开发时应该更倾向于选择组合而不是继承”的建议,为什么建议我们更倾向于而不是完全代替呢,因为当类 A 能完全代替另一个类 B(我们想让 B 成为 A 的父类)时,我们就应该使用继承,如果 A 仅仅是和 B 有着某些共同的行为,是不应该使用继承的(更多的讨论戳我)。然而,在我阅读别人的源码时,滥用继承的情况实在是太多了,多少人创建了一个 BaseActivity 后,就让所有 Activity 继承它,在子 Activity 中实现业务逻辑。

而且这样做问题大大的有,最鲜活的例子就是:Joe Newguy 加入到我们组,并实现了 ShinyFeatureActivity,那会组里没有任何规定强迫他必须让 ShinyFeatureActivity 继承于 BaseActivity,但他还是这么干了……万幸我们在 Code Review 时发现了这个问题。此外,如果每一个 Activity 都继承于 BaseActivity,在某些情况下,你可能要继承的是其他 Activity(例如:PreferenceActivity、ListActivity)。尽管大部分 Activity 的子类都有相应的 Fragment 代替,但还是有一部分是没有对应 Fragment 的,某些库仍然需要相应的 Activity 子类。

有些更潜在的问题是:有时候某些 Activity 需要这些行为,其他的 Activity 需要其他行为,而 Java 并不支持多继承,这就意味着我们得将行为有交集的 Activity 的所有行为放到一个独立的类里面。但这样做会降低可维护性,甚至带来性能影响。

事实上,我们会这么干的动机很简单:代码复用。确实,代码复用很重要。而我们大部分公共逻辑需要在 Activity 生命周期的某一环实现。但 Application.ActivityLifecycleCallbacks 是一个让人很蛋疼的玩意,而且可能需要在 Application.onCreate() 方法里注册它,最讽刺的是:我们想尽办法避免在 Application.onCreate() 方法里注册它……

这也是无绑定 View 的 Fragment 的由来了,当无数 Android 开发者把 Fragment 看作 UI 组件时,事实上 Fragment 更像生命周期的组件。为什么要说这些 Fragment 是无绑定 View 的呢?因为在这些开发者的手里,Fragment 的 onCreateView() 方法既没有被重写,也没有返回 null。本质上,Fragment 就是一个能够处理或操控事件的组件,而它自身没有对应的 View。

为了区分无绑定 View 的 Fragment 和面向 View 的 Fragemnt,我在命名时会将无绑定 View 的 Fragemnt 命名为 * XXHelper*,其他的就命名为XXFragment。例如,AnalyticsHelper 代表的就是关联分析逻辑的 Fragment,而 HeaderFragment 则显示了一个标题栏。当然了,大家可以尝试这么干,也可以无视我的建议,我自己是感觉满有用的哈~

因为这些无绑定 View 的 Fragment 里面没有 UI 组件,也就意味着在这些 Fragment 里我们不需要考虑初始化布局所需的 Layout-ID,或者是 View 需要的动画,那么我们完全可以用工厂模式开发这些 Fragment,提高工厂方法的易用性和可操控性。就这一点来说,他们还能完成添加 Fragment 自身的操作,我创建了一个 Gist 来为大家介绍要怎么做到,有兴趣的话可以点进去看看哈。如果使用 Android-Studio 进行开发的话,你可以将它添加到设置的 File and Code Templates 选项中,然后当你创建一个新的类时,在 Kind 下拉选项中选择它。

将 FooHelper 添加到它的父类中非常简单,只要调用 FooHelper.attach(this) 就可以了。但如果相应的父类没有实现 FooHelper 的回调接口的话会出现编译错误,此外,如果 attach() 方法已经被调用了,该方法的返回值会是之前的 Fragment。这个 Gist 包含对 Fragment 和 Activity 的重载,而且将它们转换为使用支持的 Fragement 和 FragmentActivity,其中的意义非常中大。而且它还包含了 FragmentUtils.getParent() 的简化版 —— getParent() 方法(详情戳我)。

显然,无绑定 View 的 Fragment 比 BaseActivity 好用得多,它们很好地封装了需要生命周期回调(或者是 onActivityResult(),FragmentManager)的处理方法。最棒的是,我们可以将 Activity 共用的某些逻辑分解到职责单一的模块组件中,Activity 需要什么逻辑,就选择什么模块使用。如果你的 Activity 大部分都需要许多相同的模块,那么你没有理由不实现 CommonComponentsHelper 用于处理这些共用逻辑,而且你也不需要把 Activity 的所有共用依赖放在一个基类中。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 03:38:18

用组合代替继承能为 Activity 带来什么的相关文章

Java编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)

1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非所嵌入对象的接口.为取得此效果,需要在新类中嵌入一个现有类的private对象.但有时,允许类的用户直接访问新类中的组合成分是极具意义的,即将成员对象声明为public.如果成员对象自身都隐藏了具体实现,那么这种做法是安全的.当用户能够了

(转)组合优于继承---设计模式之策略模式

文章来源:http://www.javaeye.com/topic/328262 当我们掌握了Java的语法,当我们了解了面向对象的封装.继承.多态等特性,当我们可以用Swing.Servlet.JSP技术构建桌面以及Web应用,不意味着我们可以写出面向对象的程序,不意味着我们可以很好的实现代码复用,弹性维护,不意味着我们可以实现在维护.扩展基础上的代码复用.一把刀,可以使你制敌于无形而于江湖扬名,也可以只是一把利刃而使你切菜平静.Java,就是这把刀,它的威力取决于你使用的方式.当我们陷入无尽

day26--静态属性、类方法、静态方法、组合、继承

一.静态属性 class Room: tag=1 def __init__(self,name,owner,width,length,heigh): self.name=name self.owner=owner self.width=width self.length=length self.heigh=heigh @property def cal_area(self): # print('%s 住的 %s 总面积是%s' % (self.owner,self.name, self.widt

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以

组合与继承有什么区别

组合和继承是面向对象中两种代码复用的方式.组合是指在新类里面创建原有类的对象,重复利用已有类的功能.继承是面向对象的主要特性之一,它允许设计人员根据其它类的实现来定义一个类的实现.组合和继承都允许在新的类中设置子对象(subobject),只是组合是显式的,而继承则是隐式的.组合和继承存在着对应关系:组合中的整体类和继承中的子类对应,组合中的局部类和继承中的父类对应. 二者的区别在哪里呢?首先分析一个实例.Car表示汽车对象,Vehicle表示交通工具对象,Tire表示轮胎对象.三者的类关系下图

组合优于继承

原文地址:http://leihuang.org/2014/11/18/composition-inheritance/ 为什么组合优于继承? 这是一个非常典型的设计模式的问题,Head First Design Pattern第一章好像就讲了,之前看得有点忘了.以下我把stackoverflow上面得分比較高的答案搬过来用一下,我认为这样更easy理解些. 两者差别 Think of composition as a has a relationship. A car "has an"

组合查询——继承与多态的小练习

上次个人版机房收费做的时候,组合查询这里做的不好,没有抽出模板,导致感觉有很多冗余,这次自己挑U层,一方面是感觉自己的B层和D层做的可以提升的空间目前很小了,另一方面就是想加强一下自己对细节的注意问题. 上次组合查询是这样的,以代码为例: U层代码如下: Imports System.Collections '引入HashTable类 Public Class frmColWorkInfo Dim HtZD As New Hashtable '定义处理字段名转换的hashtable Dim Ht

组合与继承

组合与继承 Java 继承 组合 1. 组合 组合:只需在新的类中产生现有类的对象.由于新的类由现有类的对象组成,所以称为组合.(只是复用了现有程序代码的功能,而非它的形式)如下: class A{ private int a = 10: private int b; private float c; } public class B{ private String str; private A a = new A(); pubblic String tostring(){ System.out

细学设计模式一(组合与继承)

1 <?php 2 abstract class Lesson{ 3 protected $duration; 4 const FIXED = 1; 5 const TIMED = 2; 6 private $costtype; 7 8 function __construct($duration,$costtype){ 9 $this->duration = $duration; 10 $this->costtype = $costtype; 11 } 12 13 function c