2010-07-14 35 views
4

我有一个抽象类A和它的几个实现。我期望通过添加更多的实现来随着时间的推移而发展。哪种设计模式允许基于运行时类型的功能抽象?

我也有一个接口,在上面的类层次结构的实例(例如打印它们)做一些事情。

我希望接口的实现为A的某些子类提供一些特殊功能,并为其余的子类提供默认功能。

我希望这个例子阐明事情:

abstract class A { } 
class B extends A { } 
class C extends A { } 

interface Processor { 
    public void process(A a); 
} 

class SimpleProcessor implements Processor { 

    //I want this to be called when argument is instance of A or C or any 
    //new class that will be added in the future 
    public void process(A a) { 
     //Line 14 
     System.out.println("Default processing"); 
    } 

    //I want this to be called when argument is instance of B 
    public void process(B b) { 
     System.out.println("Special processing"); 
    } 

} 

public class Runner { 

    public static void main(String[] args) { 
     B b = new B(); 
     Processor p = new SimpleProcessor(); 
     p.process(b); 
    } 

} 

的示例打印 “默认处理”。问题是要执行的方法是根据接口方法的编译时类型来选择的。有没有一种方法(或设计模式),使这个程序打印“特别处理”,而不在第14行加入

if (a instance of B) 
    process((B) a); 

列表为每一个需要特别处理类?

我看了一下visitor模式,但它看起来没有什么改进,因为我不想用A的每个子类的方法“污染”处理器接口,因为会添加更多的A子类。

换一种方式,我想接口的实现:

  • 提供的
  • 具体子类的方法的自定义实现提供了将在被添加类的默认实现未来
  • 避免列出所有的类在一个大的if-then-else的列表

谢谢!

+0

你正在寻找的模式被称为“可覆盖的方法”... – 2010-07-14 10:58:11

+0

策略模式? – 2010-07-14 13:27:37

+0

谢谢大家的回复。我最终使用了if-then-else语句测试的例子列表。 – idrosid 2010-07-15 08:00:57

回答

3

如果您创建一个适配器,接受要处理的对象并返回该对象的处理器,那么该怎么办?

if A -> return ProcessorA 
if B -> return ProcessorB 

代码例如:

class Adapter { 

    Processor getProcessor(Object o) { 
     if (o instance of A) { 
      return new ProcessorA(); 
     } else if ... 
    } 

} 
+0

感谢您的回复。我正在考虑类似的东西。创建一个AbstractProcessor实现,该实现已为A的每个子类重载方法,并使用if-then-else语句创建入口方法。在如果我可以有明确的转换到A的特定子类的内部。因此,处理器的子类可以处理新类型的A,并且我可以添加处理器而不需要对A或子类进行任何更改。但是我担心的是,看起来不像OO那样拥有巨大的if-then-else块来测试类型。我想知道是否有更好的方法。 – idrosid 2010-07-14 11:06:38

+0

你可以把属性文件或XML映射,然后你就不会有一个大的if-then-else列表。或者...让我尝试先编码它... – nanda 2010-07-14 11:21:46

+0

+1适配器是比扩展主类和使用简单的polymorfism更好的选择,因为它有助于保持“服务”代码(记录,打印,绘图,.. )出主班。 – 2010-07-14 11:38:26

4

移动代码分成而变化,并使用多态性的类型。见Open Closed Principle

interface Processable { 
    void process(); 
} 

abstract class A implements Processable { 
    public void process() { 
     System.out.println("Default processing"); 
    } 
} 
class B extends A { 
    public void process() { 
     System.out.println("Special processing"); 
    } 
} 
class C extends A { 
    // default implementation inherited from A 
} 


class SimpleProcessor { 
    public void process(Processable p) { 
     p.process() 
    } 
} 

public class Runner { 
    public static void main(String[] args) { 
     B b = new B(); 
     Processor p = new SimpleProcessor(); 
     p.process(b); 
    } 
} 
+0

感谢您的回复。 问题是我想有很多处理器实现。 为了使事情更具体,A类是一个UI小部件,Processor是这些小部件的渲染器。我希望能够添加更多渲染器(例如更多皮肤)。我还想添加更多的小部件(通过继承现有的小部件),并且只能更新一些渲染器。 因此,A和处理器的两个子类都有所不同,所以您建议的方法不能解决问题。 – idrosid 2010-07-14 11:00:08

+2

问题在于,您必须在类别中放置大量“服务”代码,这些代码不应该关注这些服务(日志记录,打印,绘图等)。使用适配器非常灵活,并使“服务”代码不在主要类中。 – 2010-07-14 11:37:09

0

这是使用Adapter的进一步改进。这种解决方案需要思考图书馆来源:http://code.google.com/p/reflections/

优势:

  • 没有如果再用的instanceof其他
  • 没有配置

缺点:

  • 需要思考图书馆
  • 可以在一开始是缓慢

这是它:

import java.lang.reflect.ParameterizedType; 

public abstract class Processor<T> { 

    private final Class<T> processedClass; 

    public Processor() { 
     ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass(); 
     processedClass = (Class<T>) parameterizedType.getActualTypeArguments()[0]; 
    } 

    public Class<T> getProcessedClass() { 
     return processedClass; 
    } 

    protected abstract void process(T message); 

} 

public class A { 

} 

public class B { 

} 

public class ProcessorA extends Processor<A> { 

    @Override 
    protected void process(A message) { 
     System.out.println("Processing object A"); 
    } 

} 

public class ProcessorB extends Processor<B> { 

    @Override 
    protected void process(B message) { 
     System.out.println("Processing object B"); 
    } 

} 

import java.lang.reflect.Constructor; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.Set; 

import org.reflections.Reflections; 

public class Adapter { 

    private Map<Class<?>, Processor<Class<?>>> mapping = new HashMap<Class<?>, Processor<Class<?>>>(); 

    public Adapter() throws Exception { 
     Reflections r = new Reflections(""); 
     Set<Class<? extends Processor>> subTypesOf = r.getSubTypesOf(Processor.class); 

     for (Iterator iterator = subTypesOf.iterator(); iterator.hasNext();) { 
      Class<? extends Processor> c = (Class<? extends Processor>) iterator.next(); 
      Constructor<? extends Processor> constructor = c.getConstructor(); 
      Processor p = constructor.newInstance(); 
      mapping.put(p.getProcessedClass(), p); 
     } 
    } 

    public <T> Processor<T> getProcessor(T obj) { 
     return (Processor<T>) mapping.get(obj.getClass()); 
    } 
} 

public class Main { 

    public static void main(String[] args) 
      throws Exception { 
     Adapter adapter = new Adapter(); 

     A a = new A(); 

     adapter.getProcessor(a).process(a); 

     B b = new B(); 

     adapter.getProcessor(b).process(b); 
    } 

} 

结果:

14:01:37.640 [main] INFO org.reflections.Reflections - Reflections took 375 ms to scan 4 urls, producing 222 keys and 919 values 
Processing object A 
Processing object B 
1

您可以让类本身返回处理器

interface Widget { 
    Processor getProcessor(); 
} 
interface Processor { 
    void process(Widget w); 
} 
abstract class WidgetA implements Widget { 
    Processor getProcessor() { 
     return new Processor() { 
     void process(Widget w) {// do magic default process stuff} 
     }; 
    } 
} 
class WidgetB extends WidgetA { 
    // uses default processor 
} 
class WidgetC extends WidgetA { 
    Processor getProcessor() { 
     return new Processor() { 
     void process(Widget w) {// do magic widget C process stuff} 
     }; 
    } 
} 

然而对于不同的皮肤故事,也许它会更好创建一个处理器工厂,取决于部件返回合适的处理器,为不同的皮肤,那么你可以创建ProcessorFactory取决于其皮肤使用

interface ProcessorFactory { 
    Processor getWidgetAProcessor(); 
    .... 
} 



abstract class WidgetA implements Widget { 
    Processor getProcessor() { 
     return factory.getWidgetAProccesor(); 
    } 

    void setProcessorFactory(ProcessorFactory pf) { 
     this.factory = pf; // move method signature also to interface 
    } 
} 

注:这只是一个想法,肯定不是最好的解决办法我认为

1

如何为每个对象创建Processor实现,然后将它们注册到CompositeProcessor中,例如

public class ProcessorB implements Processor 
{ 
    public void process(A input) { // do something here for B. } 
} 
public class ProcessorC implements Processor 
{ 
    public void process(A input) { // do something here for C} 
} 
// add more processors if needed 

public class CompositeProcessor implements Processor 
{ 
    private Map<Class,Processor> processors; 
    public CompositeProcessor(Map<Class,Processor> processors) 
    { 
      this.processors=processors; 
    } 
    public void process(A input) 
    { 
      for (Map.Entry<Class<?>,Processor> entry : processors.entries()) 
      { 
       if (entry.getKey().isAssignableFrom(input.getClass()) 
       { 
        entry.getValue().process(input); 
        return; 
       } 
      } 
      // do default processing here 
    } 
} 

现在在Runner类中使用CompositeProcessor。

注意:我没有编译上面的代码,只是在这个编辑器中输入,因此可能会出现一些错误,但是您有想法:)。

一些优点是: - 处理器与其处理的类分离(例如A和ProcessorA分开)。 - 可能有多于1个处理器的给定对象 - 处理器的映射可以在运行时更改

0

模板方法。

基类实现默认行为,派生类实现特定的行为。

Class BaseWithTemplateMethod { 
    void process() { 
    // Default behavior goes here 
    } 
} 

Class DerivedWithSpecific extends BaseWithTemplate { 
    @override 
    void process() { 
    // Specific behavior goes here 
    } 
} 

你可以做到这一点的主题很多变化,比如在另一个类封装的行为,在运行时配置的情况下,为他们使用的具体行为,实质上是使用组成代替。这在Java和没有多重继承的其他语言中特别有用。