每次面试都会被问到一些设计模式的题目。
而且面试官还是不停是追问一些具体的模式及其区别。
我在这里想提出一些新思维。
设计模式,其实是面向一些常用的应用场景所给出的编码方式的经验。
而编码方式的玄妙之处无非是特性之一的接口在Java一些特性中的组合而已。
比如策略模式,就可以概括为将一个接口作为一个类的属性而已。因为一个类的属性肯定是要用的,而接口唯一被用的方式就是调用接口方法。
在算法场景下,当传入接口的不同实现类设置进这个类的属性时,就形成了大家熟悉的策略模式了。
那么在广义的场景下,接口代表着一种行为。这就是广义上的行为策略模式,这个时候理解这句话:针对接口编程,就容易的多。
再比如接口1实现类的一个属性是接口2,这就是个大模式,根据各自不同的情况就变成了不同的模式。
如果接口1和接口2是同一个接口,那就可以是代理模式,装饰模式等。
如果接口1和接口2不是同一个接口,那就是适配器模式。
可是写了那么多模式,用了那么多模式,发现每到一个新的项目或模块,整套又要重写一遍。因为这时候应用到的模型的类型不一样了。
如果将现有的模式的版本改造成泛型的版本,那就意味着放之四海而皆准了,就像java提供的泛型集合一样。
当然也许有人会问,不同的项目或者模块也许大框架一样,但是传递的参数个数不一样怎么办呢?
虽然说java中已经提供了任意个数参数的功能,但是用作模式里似乎不太合适。
那么可以用一种通用的接口或类来代替可变参数,叫元组类Tuple。很多基础工具类库中都有这个类,如果平时不阅读底层工具库的源代码一般注意不到有这么一个工具类。
下面是同步的分发器或者叫观察者模式的泛型实现。
public interface ISource<T>{
T getSource();
}
public interface IEvent<ET,T> extends ISource<T>{
ET getType();
}
public interface IHandler<E>{
void handle( E event );
}
public interface IDispatcher<H,E,ET>{
void register( ET eventType, H handler );
void unregister( ET eventType, H handler );
void remove( H handler );
void fire( E event );
}
class ServiceDispatcher<H extends IHandler, E extends IEvent<ET,T>, ET, T> implements IDispatcher<H,E,ET>{
private ConcurrentMap<ET, Set<H>> handlerMaps = new ConcurrentHashMap<ET, Set<H>>();
public void register( ET eventType, H handler ){
Set<H> handlers = nullSafeGet( eventType );
handlers.add( handler );
}
public void unregister( ET eventType, H handler ){
Set<H> handlers = nullSafeGet( eventType );
if( handlers.contains( handler ) ){
handlers.remove( handler );
}
}
public void remove( H handler ){
for( Map.Entry<ET, Set<H>> entry : handlerMaps.entrySet() ){
entry.getValue().remove( handler );
}
}
void fire( E event ){
Set<H> handlers = handlerMaps.get( event.getType() );
for( H handler : handlers ){
handler.handle( event );
}
}
private Set<H> nullSafeGet( ET eventType ){
Set<H> handlers = hanlderMaps.get( eventType );
if( handlers == null ){
handlers = new CopyOnWriteArraySet<H>();
handlerMaps.putIfAbsent( eventType, handlers );
}
return handlers;
}
}
当然这里类泛型限定E, ET为某种类型,
也可以采用方法泛型的方式来支持更为广泛的分发,这在Android的EventBus中就是这种典型的应用。
class DefaultDispatcher{
private ConcurrentMap<Class<?>, Set<IHandler<?>> handlerMaps = new ConcurrentHashMap<ET, Set<IHandler<?>>();
public <T> boolean dispatch( T obj ){
}
public void register( Class<?> clazz, IHandler<?> handler ){}
public void unregister( Class<?> clazz, IHandler<?> handler ){}
}