软件设计-模块化设计初思考二
模块化设计初思考二
书接上回
我们已经
设计了Sender接口 用来实现信息的发送,为此我们做了两个实现类,分别实现,邮箱发送与短信发送。(实现类,未实现功能)
设计了 Verify接口 用来实现 不同的验证方式 为此我们做了两个实现类 ,分别实现,邮箱验证与账号验证。(实现类,未实现功能)
我们将接口聚合于 AccountModularity 类 代码如下
package com.ss.account.main;
import com.ss.account.sender.MailSender;
import com.ss.account.sender.Sender;
import com.ss.account.verify.MailVerify;
import com.ss.account.verify.Verify;
public class AccountModularity {
//发送接口 实现
private Sender sender;
//验证接口 实现
private Verify verify;
public AccountModularity() {
init();
}
private void init() {
sender = new MailSender();
verify = new MailVerify();
}
private String sendVerifyCode(String account) {
//TODO 处理逻辑
String code = "123asd";
return sender.sendVerifyCode(account,code) ? code : null;
}
public boolean verifyAccount(String account) {
//TODO 处理逻辑
return verify.verifyAccount(account);
}
}
AccountModularity类的升级
今天我们要对这个类进行升级
升级之前,我们在看看需要的功能:
- 登录
- 注册
- 修改个人信息
- 验证账号是否存在(隐藏功能)
首先,我们来分析一下,具体功能
登录
登录 所需要的参数 可以是 邮箱 账号 手机号 。。。
返回的参数可以是 用户实体类,
问题:
1、用户实体类 不能固定,应该根据不同的实体类返回值不同
2、登录时、参数不同。
解决
1、可以将 用户实体类 抽象出来,作为泛型。
2、可以将具体不同的验证抽象出来,没错,我们已经抽象出来了 就是 Verify接口 还记得其作用吗? 实现不同的验证方式。
同理可得 注册修改密码 需要使用泛型 是否需要不同的接口,我们再行思考。
于此 ,我们已经发现,AccountModularity 并不是一个实现类,而是定义了一套规范,因此,我们将其做成具有泛型的抽象类。
代码如下:
package com.ss.account.main;
import com.ss.account.sender.Sender;
import com.ss.account.verify.Verify;
import com.ss.main.BaseModularity;
import com.ss.main.Lifecycle;
/**
* @author Jangs
* @param <T> 用户类
*/
public abstract class AccountModularity<T> {
//发送接口 实现
protected Sender sender;
//验证接口 实现
protected Verify verify;
/**
* 保护构造器
*/
protected AccountModularity() {
}
/**
* 发送 验证码
* @param account 用户
* @return String 验证码
*/
protected abstract String sendVerifyCode(String account) ;
/**
* 验证用户是否存在
* @param account 用户
* @return boolean 是否存在
*/
protected abstract boolean verifyAccount(String account);
/**
* 登录
* @return T 用户实体类
*/
protected abstract T login();
/**
* 注册
* @param t 用户实体类
*/
protected abstract void register(T t);
/**
* 修改个人信息
* @param t 用户实体类
*/
protected abstract void updateAccountInfo(T t);
}
边界化
在此,我提出模块化开发的一个理解 : 边界化
说明
1、模块内的所有方法,都必须是不能直接被外部访问的
2、提供一个 public 入口方法,来调用其他方法。
举一个例子
我们设计了一个房子,在房子内部 设计了它很多的功能,可以做饭,可以洗澡,可以睡觉,但是这些内容都是在房子内部完成的。
如果,我们想要去做饭,我们应该怎么办?
我们需要从门口进入,进入厨房,做饭,出厨房的同时带出饭菜。
这是一整套流程,
我们模块内的所有方法,都必须是不能直接被外部访问的,如果可以直接被外部访问,就好像,我们去做饭不需要进房间一样,那么房子的意义在哪里呢?(家徒无四壁)。别人可以随随便便的进入你家的厨房,去你家洗澡,碎觉。
再举一个例子
我们是一个人,我们可能做很多的事情,但是,当我们需要别人的帮助时,比方,需要他人借给我点钱。
这时我们需要怎么做呢?
直接掏他的口袋,去拿钱?且不说能不能成功,你伸进去的时候,你也被打了。而且,现在都是电子货币。
那正常情况下,我们需要怎么做呢?
第一步、我们需要通知他,我想借点钱。
第二步、由他自己决定,要不要,借钱给我们。
我们不能主宰别人的行为,我们需要通知告知Ta 让Ta 自己来做。
因此,我们的 AccountModularity类 需要以下几项优化
1、将类,修改成抽象类, AbstractAccountModularity类
2、我们需要提供一个 入口方法,鉴于,以后的模块都需要此方法,我们直接抽象成抽象类BaseModularity (仅 提供入口方法)
入口抽象类
代码如下:
package com.ss.main;
/**
* @author Jangs
* 此类 仅提供入口方法
*/
public abstract class BaseModularity {
/**
* 入口方法
*/
public abstract void doService();
}
再来
我们设计一个房子(模块) 但是,我们也仅仅是提供各种可能性,具体建设,我们不能定义,最后,销毁,我们不可定义
所以,我设计一个生命周期接口,去统一所有模块的初始化与销毁工作。
Lifecycle接口
package com.ss.main;
/**
* @author Jangs
*/
public interface Lifecycle {
/**
* 初始化
*/
void init();
/**
* 销毁
*/
void destroy();
}
设计此模块的好处如下“
1、统一初始化与销毁
2、为后期多模块组合,树状初始化做装备。
最后我们优化的
本期最终优化成果
AbstractAccountModularity 如此
package com.ss.account.main;
import com.ss.account.sender.Sender;
import com.ss.account.verify.Verify;
import com.ss.main.BaseModularity;
import com.ss.main.Lifecycle;
/**
* @author Jangs
* @param <T> 用户类
*/
public abstract class AbstractAccountModularity<T> extends BaseModularity implements Lifecycle {
//发送接口 实现
protected Sender sender;
//验证接口 实现
protected Verify verify;
/**
* 发送 验证码
* @param account 用户
* @return String 验证码
*/
protected abstract String sendVerifyCode(String account) ;
/**
* 验证用户是否存在
* @param account 用户
* @return boolean 是否存在
*/
protected abstract boolean verifyAccount(String account);
/**
* 登录
* @return T 用户实体类
*/
protected abstract T login(String account, String password);
/**
* 注册
* @param t 用户实体类
*/
protected abstract void register(T t);
/**
* 修改个人信息
* @param t 用户实体类
*/
protected abstract void updateAccountInfo(T t);
}
自此完成
对于 用户模块的抽象已经实现并优化,但是,具体如何调用?我们下期分解
在此我提出几个问题
1、如何实现不同的验证?
2、如果以后同时实现两种验证方式,我们该如何扩展与优化?
3、如果,以后此模块需要扩展,如何扩展?
4、如果,以后需要跟其他模块一同合作,如何链接?
5、我大量使用集成,java又不能实现多继承,日后扩展如何?