在实际编程过程中,对象将表现为三种不同的形态和运行模式。
对象的运行模式是根据对象的构成特点来划分的。这三种对象的运行模式,我们分别以文字和代码来说明。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
属性--行为模式 这种模式是指一个对象同时拥有属性定义和方法定义。这是对象最为普遍的一种运行模式,绝大多数对象都运作在这种模式上之上。
观点:将对象运作在“属性-行为”模式下,最符合面向对象编程思想的本意。
为什么这么说呢?
1.当对象运行在“属性-行为”模式上时,我们能够最大程度地应用各种设计模式。
对于设计模式有深入研究的读者,应该会同意这个观点。设计模式的存在基础是对象,因而设计模式自身的分类也围绕着对象展开。我们可以发现,绝大多数的设计模式需要通过类、接口、属性、方法这些语法元素的共同配合才能完成。因而,单一的属性模式和行为模式的对象,在设计模式的应用上很难施展拳脚。
2.当对象运作在“属性-行为”模式上时,我们能够最大地发挥对象之间的协作能力。
仔细分析对象的关系模型,我们会发现无论是对象的从属关系还是对象的协作关系,它们在绝大多数情况是通过对象之间的属性引用来完成的。这种属性引用的方式,只是在形式上解决了对象和对象之间进行关联的问题。而真正谈到对象之间的配合,则不可避免地需要通过行为动作的逻辑调用来完成,这也是对象协作的本质内容。
策略模式
package org.leiwen.dp.action.stragety;
//现金收费抽象类
public abstract class CashSuper {
// 使用枚举类型表示收费类型
public enum PayType {
CASH_NORMAL, CASH_RETURN, CASH_REBATE
};
// 现金收取抽象类的抽象方法,收取现金,参数为原价,返回值为当前价
public abstract double acceptCash(double money);
}
public class CashNormal extends CashSuper {
//正常收费,原价返回
public double acceptCash(double money) {
return money;
}
}
public class CashRebate extends CashSuper {
private double moneyRebate = 1;
//打折收费,初始化时,需要输入折扣率,如八折,就是0.8
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
public double acceptCash(double money) {
return money * moneyRebate;
}
}
public class CashReturn extends CashSuper {
private double moneyCondition = 0.0;
private double moneyReturn = 0.0;
// 返利收费,初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition=300,moneyReturn=100
public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
public double acceptCash(double money) {
double result = money;
//若大于返利条件,则需要减去返利值
if (money >= moneyCondition) {
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
public class CashFactory {
public static CashSuper createCashAccept(PayType payType) {
CashSuper cs = null;
// 根据条件返回相应的对象
switch (payType) {
case CASH_NORMAL:
cs = new CashNormal();
break;
case CASH_RETURN:
cs = new CashReturn(200, 100);
break;
case CASH_REBATE:
cs = new CashRebate(0.8);
break;
default:
break;
}
return cs;
}
}
//策略模式实现
public class CashContext {
private CashSuper cs;
//通过构造方法,传入具体的收费策略
public CashContext(CashSuper cs) {
this.cs = cs;
}
public double getResult(double money) {
//根据收费策略的不同,获得计算结果
return cs.acceptCash(money);
}
}
public class StragetyTest {
public static void main(String[] args) {
// 测试策略模式的实现
CashSuper cs = CashFactory
.createCashAccept(PayType.CASH_REBATE);
CashContext context = new CashContext(cs);
double money = context.getResult(200);
System.out.println("实收:" + money + "元");
}
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
属性模式 这种模式是指一个对象只拥有属性定义,抚之以相应的setter和getter方法。Java规范为运行在这种模式下的对象取了一个统一的名称:JavaBean。
JavaBean从其表现出来的特性看,可以作为数据的存储模式和数据的传输载体。
//注册用户
public class User{
private Integer id;
private String name;
private String email;
//这里省略了所有的getter和setter方法
}
观点:JavaBean对象的产生,主要是为了强调对象的内在特性的状态,同时构造一个数据存储和数据传输的载体。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
行为模式
这种模式是指构成一个对象的主体是一系列方法的定义,而并不含有具体的属性定义,或者说即使含有一些属性定义,也是一些无状态的协作对象。运行在这种模式之下的对象,我们往往称之为“无状态对象”,其中最为常见的例子是我们熟悉的Servlet对象。
所谓的无状态对象实际上就是指对象的方法所表达的行为特性并不依赖于对象的内部属性的状态。
而这种无状态的对象,非常适合进行一个请求的响应,并在方法体的内部实现中,进行复杂的业务逻辑处理。
/**
*Struts2框架中的Http请求中的处理类,实现了Servlet标准中的Filter接口
*/
public class
StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
// 进行Http请求预处理的操作类
protected PrepareOperations prepare;
// 进行Http请求的逻辑执行处理类
protected ExecuteOperations execute;
// 配置哪些形式的URL模式被排除在Struts2的处理之外
protected List<Pattern> excludedPatterns = null;
/**
* 创建Dispatcher,此类是一个Delegate,它是真正完成url解析,读取对应Action的地方
*
* Filter的初始化过程
*
* init方法的主要内容是针对Dispatcher(核心分发器)、PrepareOperations(Http预处理类)
* 和ExecuteOperations(Http处理逻辑执行类)这3个元素展开的。
*/
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化操作类
InitOperations init = new InitOperations();
try {
// filterConfig对象由Web容器传递进来的
FilterHostConfig config = new FilterHostConfig(filterConfig);
// 初始化日志,FilterHostConfig实现了HostConfig接口
init.initLogging(config);
// 初始化核心分发器Dispatcher
Dispatcher dispatcher = init.initDispatcher(config);
// 初始化静态资源加载器
init.initStaticContentLoader(config, dispatcher);
// 初始化进行Http请求预处理的操作类
prepare = new PrepareOperations(filterConfig.getServletContext(),
dispatcher);
// 初始化进行Http请求处理的逻辑执行的操作类
execute = new ExecuteOperations(filterConfig.getServletContext(),
dispatcher);
// 初始化被Struts2排除在外的URL模式
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
// 自定义的初始化过程,留作用户扩展
postInit(dispatcher, filterConfig);
} finally {
// 初始化中的清理工作
init.cleanup();
}
}
/**
* Callback for post initialization 初始化中的扩展工作
*/
protected void postInit(Dispatcher dispatcher, FilterConfig filterConfig) {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
// PerpareOperations对象本身只是一个操作代理接口,真正完成逻辑功能的是Dispatcher本身。
// PerpareOperations在内部实现中所做的,只是对每个操作做了一个简单的转发处理。
// ==== 步骤1开始====
// 设置Encoding和Locale,Encoding和Locale是Web页面上的重要属性,也是Web程序进行国际化处理的核心参数。
// 因而在Http请求预处理的第一步就做这两个参数的设置也相当合理。
prepare.setEncodingAndLocale(request, response);
// ==== 步骤1结束====
// ==== 步骤2开始====
// 创建Action执行对应的ActionContext
prepare.createActionContext(request, response);
// ==== 步骤2结束====
// ==== 步骤3开始====
// 把核心分发器Dispatcher绑定到当前线程
prepare.assignDispatcherToThread();
// ==== 步骤3结束====
// 处理被过滤的URL
if (excludedPatterns != null
&& prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
// 真正需要进行URL处理的逻辑开始
// ==== 步骤4开始====
// 首先对request进行一定的封装
request = prepare.wrapRequest(request);
// ==== 步骤4结束====
// ==== 步骤5开始====
// 根据url取得对应的Action的配置信息--ActionMapping,actionMapper是通过Container的inject注入的
ActionMapping mapping = prepare.findActionMapping(request,
response, true);
// 从数据结构上看,ActionMapping只是一个很普通的Java对象,然而它却意义非凡,因为它所表达的意思是将一个URL
// 形式的Http请求与Struts2中的Action建立起关系来。ActionMapper才是Struts2进行URL
// Mapping关系查找的核心类。
// ==== 步骤5结束====
// 没有找到对应的ActionMapping
if (mapping == null) {
// 判断是否将URL处理为静态资源
boolean handled = execute.executeStaticResourceRequest(
request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
// 执行URL请求的处理
//将所有的参数传入Dispatcher中执行逻辑
execute.executeAction(request, response, mapping);
}
}
} finally {
// 清理request
prepare.cleanupRequest(request);
}
}
public void destroy() {
// 清理核心分发器dispatcher
prepare.cleanupDispatcher();
}
}