定义
针对一组算法,把他们封装到共同的接口类中,从而使得它们可以达到相互替换的目的。
演化
1.实现一个学籍管理系统的主页,可以允许老师和学生登录。两者能看到主页页面相似,但也存在着一些差别。在这种情况下,如果单独为两者各创建一个主页就会显得浪费了。因此我们一般会在主页里边通过身份判断来执行有差异的功能。如加载页面控件:
public class MainPager {
public static final int TYPE_STUDENT = 0;
public static final int TYPE_TEACHER = 1;
private int type;
public void initView() {
if (type == TYPE_STUDENT) {
// 学生页面展示逻辑
} else {
// 教师页面展示逻辑
}
}
}
这段代码不多,也能很清晰的展示出不同身份之间的差异
2.增加更多的身份,如班主任,校长之类的。现在这个页面的判断逻辑已经比较复杂了。
public class MainPager {
public static final int TYPE_STUDENT = 0;
public static final int TYPE_TEACHER = 1;
public static final int TYPE_HEADER_TEACHER = 2;
public static final int TYPE_SCHOOL_MASTER = 3;
private int type;
public void initView() {
switch (type) {
case TYPE_STUDENT:
// 学生页面展示逻辑
break;
case TYPE_TEACHER:
// 教师页面展示逻辑
break;
case TYPE_HEADER_TEACHER:
// 班主任页面展示逻辑
break;
case TYPE_SCHOOL_MASTER:
// 校长页面展示逻辑
break;
default:
break;
}
}
}
这时initView()方法的内容就过多了,阅读性变差了。很难找出每种身份对应的处理逻辑。然后再给主页增加功能。如增加数据处理initData(),增加校验帐号的逻辑checkAccount()。你会发现每个方法里都充满了switch语句。这些方法动辄就是上百行的执行逻辑,想要找到每种身份的的执行逻辑就变得相当复杂。
3.有没有办法减少判断呢?我们可以把不同身份的执行逻辑分类。在页面初始化的时候根据身份选则其中一个,之后就可以省去这部分的流程了。
(1) 先定义需要需要区别执行的方法接口
public interface Strategy {
void initView();
void initData();
void initEvent();
void checkAccount();
}
(2) 定义各个身份下的具体实现,这里仅以学生为例
public class StudentStrategy implements Strategy{
@Override
public void initView() {
// 学生页面展示逻辑
}
@Override
public void initData() {
// 学生数据处理逻辑
}
@Override
public void initEvent() {
// 学生事件处理逻辑
}
@Override
public void checkAccount() {
// 学生帐号校验逻辑
}
}
(3) 主页初始化时根据当前身份,初始化对应的Strategy。然后后续的所有逻辑都交给该Strategy处理。
public class MainPager {
public static final int TYPE_STUDENT = 0;
public static final int TYPE_TEACHER = 1;
public static final int TYPE_HEADER_TEACHER = 2;
public static final int TYPE_SCHOOL_MASTER = 3;
private int type;
private Strategy mStrategy;
public void initStrategy() {
switch (type) {
case TYPE_STUDENT:
mStrategy = new StudentStrategy();
break;
case TYPE_TEACHER:
mStrategy = new TeacherStrategy();
break;
case TYPE_HEADER_TEACHER:
mStrategy = new HeaderStrategy();
break;
case TYPE_SCHOOL_MASTER:
mStrategy = new MasterStrategy();
break;
default:
mStrategy = new StudentStrategy();
break;
}
}
private void initView() {
mStrategy.initView();
}
private void initData() {
mStrategy.initData();
}
private void initEvent() {
mStrategy.initEvent();
}
private void checkAccount() {
mStrategy.checkAccount();
}
}
此时,各种身份下的处理逻辑各自分类,可读性大大加强。当增加新的身份时,只需要新增对应Strategy实现类即可。同时主页中的处理逻辑也得到了简化。
至此一个策略模式就已经完成了。
优化
1.在上述策略模式中,我们定义的Strategy实现类,是作为MainPager的辅助类出现的,在使用过程中,不可避免的要使用MainPager中的参数。为了方便在Strategy中使用这些参数,我们可以以内部的形式来定义各个实现类。
public class MainPager {
public static final int TYPE_STUDENT = 0;
public static final int TYPE_TEACHER = 1;
public static final int TYPE_HEADER_TEACHER = 2;
public static final int TYPE_SCHOOL_MASTER = 3;
private int type;
private Strategy mStrategy;
public void initStrategy() {
switch (type) {
case TYPE_STUDENT:
mStrategy = new StudentStrategy();
break;
case TYPE_TEACHER:
mStrategy = new TeacherStrategy();
break;
case TYPE_HEADER_TEACHER:
mStrategy = new HeaderStrategy();
break;
case TYPE_SCHOOL_MASTER:
mStrategy = new MasterStrategy();
break;
default:
mStrategy = new StudentStrategy();
break;
}
}
private void initView() {
mStrategy.initView();
}
private void initData() {
mStrategy.initData();
}
private void initEvent() {
mStrategy.initEvent();
}
private void checkAccount() {
mStrategy.checkAccount();
}
public class StudentStrategy implements Strategy{
@Override
public void initView() {
// 学生页面展示逻辑
}
@Override
public void initData() {
// 学生数据处理逻辑
}
@Override
public void initEvent() {
// 学生事件处理逻辑
}
@Override
public void checkAccount() {
// 学生帐号校验逻辑
}
}
public interface Strategy {
void initView();
void initData();
void initEvent();
void checkAccount();
}
}