方法类型化——将某个或某些方法(准确的说,是方法头或接口) 提升为类型,是方法型模式的共同技术基础和设计思路。
Java中以抽象类或接口类型封装该接口。Java接口的作用在此被充分展示。
策略模式中,排序策略int[]sort(int[] arr)被抽象类IntSort封装。更多的方法类型化例子在随后的章节中介绍。本节将介绍方法对象化的两个重要应用。
1. 避免类型爆炸
假定类Person有eat()方法——大家全部用筷子(final方法);有say()方法——每人说自己的方言。于是,类Person代码如3-5所示。按照“地域”可以设计Person的各种子类如BeiJin、Wuhan等——假设程序员可以容忍这样的30个子类。
再假定Person还有walk()方法——慢条斯理、风风火火等七八种实现方式。
请问,你如何面对慢条斯理的武汉人、风风火火的上海人……say()与walk()的任意组合将导致至少30*7即210个以上的Person的子类。这是不可容忍的设计。
例程3-5组合的数目
package method.strategy;
public abstract class Person{
public final void eat(){
System.out.println("用筷子");
}
abstract public void say();//每人说自己的方言
abstract public void walk();//慢条斯理、风风火火等七八种实现方式
}
为了避免类型(数量)的爆炸,可以将say()和walk()类型化,作为两个策略类层次各自封装,取名SayBehavior和WalkBehavior。于是类Person的类层次转化为方法类型或策略类WalkBehavior、SayBehavior的类层次。重构后,系统中类的数量从m*n降低为m+n+2。
例程 3 6 重构Person类
package method.strategy;
import tool.God;
public class Person{
private WalkBehavior walk = null;
private SayBehavior say = null;
public Person(){
walk = (WalkBehavior)God.create("3-6-Walk");
say = (SayBehavior)God.create("3-6-Say");
}
public final void eat(){
System.out.println("用筷子");
}
public void say(){
this.say.say();
}
public void walk(){
this.walk.walk();
}
}
此时,Person是两个策略类的环境类,它的用户App仅依赖环境类。
package method.strategy;
public class App{
public static void main(String args[]){
Person one = new Person(); //上下文对象
one.say();
one.walk();
}
}
2.无限可能性和函数接口
如果Person只有一个需要多态化的方法如say(),通常Person本身作为策略类而非定义一个SayBehavior。但是,如果say()有无穷多或者足够大的变化呢?
这时将有无穷变化的say()设计成接口类型——Java8中设计为函数接口则是合理的选择。
例程 3 7无限可能
package method.strategy;
@FunctionalInterface
public interface SayStyle{
void say();
}
package method.strategy;
public class Man{
private SayStyle say = null;
public void setSayStyle(SayStyle say){
this.say = say;
}
public final void eat(){
System.out.println("用筷子");
}
//每人说自己的方言
public void say(){
this.say.say();
}
}
package method.strategy;
public class App{
public static void test(){
Man one = new Man(); //上下文对象
SayStyle say = ()->{System.out.println("格老子");};
one.setSayStyle( say);
one.say();
}
}
此时,Man是环境类,它的用户App需要依赖环境类Man和函数接口SayStyle。
虽然说函数接口的基本目标是实现回调,但是在非框架场合,代码由客户类提供也是函数接口的正常应用。毕竟回调只是分层结构中的术语,在非分层结构中,其代码和普通多态没有任何差异。原文:http://blog.csdn.net/yqj2065/article/details/39127231