在正确的代码实现方面,我遇到了一个概念性问题,这似乎需要多个继承,在许多面向对象语言中这不是一个问题,但由于该项目是针对Android的,所以没有像多个extends
这样的东西。
我有很多来自不同基类的活动,比如简单的Activity
、TabActivity
、ListActivity
、ExpandableListActivity
等等。在所有活动中,我还需要将一些代码片段放入onStart
、onStop
、onSaveInstanceState
、onRestoreInstanceState
和其他标准事件处理程序中。
如果我有一个用于所有活动的基类,我会将代码放入一个特殊的中间派生类中,然后创建扩展它的所有活动。不幸的是,情况并非如此,因为有多个基类。但是,将相同的代码部分放入几个中间类并不是一件容易的事,imho。
另一种方法可以是创建一个helper对象,并将上述事件的所有调用委托给助手。但这需要包含helper对象,并在所有中间类中重新定义所有处理程序。因此,这里的第一种方法并没有太大的区别--仍然有很多代码重复。
如果类似的情况发生在Windows下,我会将基类子类(与安卓中的Activity
类“对应”的东西),并在那里捕获适当的消息(在一个地方)。
在Java/Android中可以做些什么呢?我知道有一些有趣的工具,比如Java仪器仪表 (有一些真实的例子),但我不是一个Java大师,也不确定在这个特定的情况下是否值得尝试。
如果我错过了其他一些像样的解决方案,请提出来。
对于那些有兴趣在Android中解决同样问题的人,我找到了一个简单的解决办法。存在应用程序类,它除其他外提供接口ActivityLifecycleCallbacks。它正是我所需要的,允许我们拦截并为所有活动的重要事件增加一些价值。这种方法的唯一缺点是它可以从API级别14开始使用,这在很多情况下是不够的(支持API级别10是当今的一个典型需求)。
发布于 2012-12-23 15:38:58
在android/java中,如果没有代码复制,恐怕无法实现您的类系统。
但是,如果将特殊的中间派生类与复合助手对象组合在一起,则可以将代码复制最小化。这被称为装潢工_模式:
class ActivityHelper {
Activity owner;
public ActivityHelper(Activity owner){/*...*/}
onStart(/*...*/){/*...*/}
}
public class MyTabActivityBase extends TabActivity {
private ActivityHelper helper;
public MyTabActivityBase(/*...*/) {
this.helper = new ActivityHelper(this);
}
protected void onStart() {
super.onStart();
this.helper.onStart();
}
// the same for onStop, onSaveInstanceState, onRestoreInstanceState,...
}
Public class MySpecialTabActivity extends MyTabActivityBase {
// non helper logic goes here ....
}
因此,您创建的每个基类都会创建一个中间基类,它将其调用委托给助手。中间基类是相同的,但它们所继承的基类除外。
发布于 2012-12-23 20:18:36
我想你是想避免错误的代码复制。我相信迈克尔·羽毛写了一篇关于这个的文章,但不幸的是我找不到它。他描述它的方式是,您可以认为您的代码有两个部分,如橘子:果皮和果肉。rind是类似于方法声明、字段声明、类声明等的东西。纸浆是这些方法内部的东西;实现。
当谈到干燥,你想避免重复纸浆。但通常在这个过程中,你会创造更多的牛皮。这没什么。
下面是一个例子:
public void method() { //rind
boolean foundSword = false;
for (Item item : items)
if (item instanceof Sword)
foundSword = true;
boolean foundShield = false;
for (Item item : items)
if (item instanceof Shield)
founShield = true;
if (foundSword && foundShield)
//...
} //rind
这可以重构为以下内容:
public void method() { //rind
if (foundSword(items) && foundShield(items))
//...
} //rind
public boolean foundSword(items) { //rind
return containsItemType(items, Sword.class);
} //rind
public boolean foundShield(items) { //rind
return containsItemType(items, Shield.class);
} //rind
public boolean containsItemType(items, Class<Item> itemClass) { //rind
for (Item item : items)
if (item.getClass() == itemClass)
return true;
return false;
} //rind
我们在这个重构中增加了大量的外皮。但是,第二个例子有一个更干净的method()
,它的干法违规较少。
您说过要避免使用装饰图案,因为它会导致代码重复。如果您查看该链接中的图像,您将看到它将只复制operation()
签名(即: rind)。对于每个类,operation()
实现(纸浆)应该是不同的。我认为您的代码最终会变得更干净,并减少纸浆复制。
发布于 2012-12-23 16:52:22
比起继承,你应该更喜欢组合。一个很好的例子是IExtension WCF框架中的.NET "模式“。您有3个接口,IExtension、IExtensibleObject和IExtensionCollection。然后,您可以通过将作曲实例添加到IExtensibleObject对象的扩展IExtensionCollection属性中,使用IExtension对象进行不同的行为。在java中,它应该是这样的,但是,您不必创建自己的IExtensioncollection实现,在添加/删除项时调用附加和分离方法。还请注意,应该由您在可扩展类中定义扩展点,该示例使用类似事件的回调机制:
import java.util.*;
interface IExtensionCollection<T> extends List<IExtension<T>> {
public T getOwner();
}
interface IExtensibleObject<T> {
IExtensionCollection<T> getExtensions();
}
interface IExtension<T> {
void attach(T target);
void detach(T target);
}
class ExtensionCollection<T>
extends LinkedList<IExtension<T>>
implements IExtensionCollection<T> {
private T owner;
public ExtensionCollection(T owner) { this.owner = owner; }
public T getOwner() { return owner; }
public boolean add(IExtension<T> e) {
boolean result = super.add(e);
if(result) e.attach(owner);
return result;
}
// TODO override remove handler
}
interface ProcessorCallback {
void processing(byte[] data);
void processed(byte[] data);
}
class Processor implements IExtensibleObject<Processor> {
private ExtensionCollection<Processor> extensions;
private Vector<ProcessorCallback> processorCallbacks;
public Processor() {
extensions = new ExtensionCollection<Processor>(this);
processorCallbacks = new Vector<ProcessorCallback>();
}
public IExtensionCollection<Processor> getExtensions() { return extensions; }
public void addHandler(ProcessorCallback cb) { processorCallbacks.add(cb); }
public void removeHandler(ProcessorCallback cb) { processorCallbacks.remove(cb); }
public void process(byte[] data) {
onProcessing(data);
// do the actual processing;
onProcessed(data);
}
protected void onProcessing(byte[] data) {
for(ProcessorCallback cb : processorCallbacks) cb.processing(data);
}
protected void onProcessed(byte[] data) {
for(ProcessorCallback cb : processorCallbacks) cb.processed(data);
}
}
class ConsoleProcessor implements IExtension<Processor> {
public ProcessorCallback console = new ProcessorCallback() {
public void processing(byte[] data) {
}
public void processed(byte[] data) {
System.out.println("processed " + data.length + " bytes...");
}
};
public void attach(Processor target) {
target.addHandler(console);
}
public void detach(Processor target) {
target.removeHandler(console);
}
}
class Main {
public static void main(String[] args) {
Processor processor = new Processor();
IExtension<Processor> console = new ConsoleProcessor();
processor.getExtensions().add(console);
processor.process(new byte[8]);
}
}
如果您能够在类之间提取公共扩展点,则这种方法具有扩展重用的好处。
https://softwareengineering.stackexchange.com/questions/180459
复制相似问题