设计模式-组合设计模式思想设计以及使用场景,保准你一听就会,看完你绝对不亏!!
1.什么是组合模式?
组合模式是结构型设计模式,它主要是如何将类和对象组装成较大的结构,并且同时保持结构的灵活和高效,这就是结构型设计模式的特点。
说回组合模式,看名字,它的组合,就代表它想要某类与某类,某对象与某对象之间组合,达到某目的,然后对外部调用来说,我不管你组合的内部是什么,有多少个内部,都与我无关,我只管组合,我依赖组合,这样内部多少种变化对于外界来说是无感知的,这样也就形成了解耦。
2.组合模式使用场景
适用场景呢比如树形结构,要一次一次调度到子节点,叶子节点,那么根节点包含子节点和叶子节点,根节点就是组合,根节点依赖下一个子节点,那在使用时就会出现递归啊或者要调度子节点的行为,这种就可以使用组合模式。
那除了树形结构,所有想要包含到组合模式用组合模式调度到其他不同类里的情况的都可以使用组合模式,统计国家与省市县的人口数据,还有规则引擎等等都可以使用这样组合模式。
那今天这个案例实战呢,我用组合模式实现用户3步认证操作,3步认证都包含在组合模式总的认证中,由总的认证模式调度到其他不同的认证模块,是不是有点迫不及待呢,那就开始吧!
3.UML类图
4.组合模式实战代码
业务是这样的,假如我需要3个认证,这三个认证我都是需要调用的,为了简化调用,而且后期加认证对使用者也是无感知的,那么这种场景就可以用组合模式。
1.第一个认证是银行信息,第二个认证是个人身份信息,第三个认证是联系人信息,他们通用的功能都是认证下信息,那我就需要定义一个接口,这个接口就叫认证接口Authentication,它的方法就是认证方法authInfo(),返回true或false,代表是否认证成功。
2.定义子类实现,银行认证类(BankAuth)实现Authentication,个人身份信息认证PersonAuth实现Authentication,联系人认证类ContactAuth实现Authentication接口,然后还要定义总的认证接口OverAllInfoAuth,也要实现Authentication接口,这样调用认证方法时就调用总的认证实现类,总的调用实现类调度到其他的子类(如:银行认证,个人信息认证,联系人认证),这就是组合模式的精髓思想。
组合模式优点简化外部系统调用,再增加子类,外部不影响使用,不用改变,适用于树形结构,递归调用,规则引擎等场景,还有其他的总的类要调度到不同的子类的情况。
代码:
Authentication接口,定义了认证信息方法。
/**
* 总的认证接口
* */
public interface Authentication {
boolean authInfo();
}
银行认证实现类,实现Authentication,实现了银行认证方法,以下是伪代码,模拟银行认证流程。
/**
* 银行认证
* */
public class BankAuth implements Authentication {
private BankInfo bankInfo;
public BankAuth(BankInfo bankInfo){
this.bankInfo=bankInfo;
}
@Override
public boolean authInfo() {
// 模拟认证逻辑
System.out.println("银行认证中....");
System.out.println("银行名称:"+bankInfo.getBankName());
System.out.println("银行卡号:"+bankInfo.getBankNo());
System.out.println("--------------------------------");
return true;
}
}
个人信息认证,实现Authentication,实现了个人信息认证,以下是伪代码,模拟个人信息认证流程。
/**
* 个人信息认证
* */
public class PersonAuth implements Authentication{
private PersonInfo personInfo;
public PersonAuth(PersonInfo personInfo){
this.personInfo=personInfo;
}
@Override
public boolean authInfo() {
// 模拟认证逻辑
System.out.println("个人身份认证中....");
System.out.println("个人名称:"+personInfo.getName());
System.out.println("个人身份证:"+personInfo.getIdCard());
System.out.println("--------------------------------");
return true;
}
}
联系人认证,实现Authentication,实现了联系人信息认证,以下是伪代码,模拟联系人信息认证流程。
/**
* 联系人认证
* */
public class ContactAuth implements Authentication{
private ContactInfo contactInfo;
public ContactAuth(ContactInfo contactInfo){
this.contactInfo=contactInfo;
}
@Override
public boolean authInfo() {
// 模拟认证逻辑
System.out.println("联系人认证中....");
System.out.println("联系人名称:"+contactInfo.getName());
System.out.println("联系人手机号:"+contactInfo.getPhone());
System.out.println("--------------------------------");
return true;
}
}
总的认证,去调度到其他认证里,定义了认证接口的变量,使用者将不同的的认证类传入进来,调用总认证的方法则会根据循环调度到不同的认证中去。
/**
* 组合模式
* 不知道几个类,不知道具体调度的是谁,主要是都要被调度到
* */
public class OverAllInfoAuth implements Authentication{
// 组合模式
private List<Authentication> listAuth=new ArrayList<>();
public OverAllInfoAuth(List<Authentication> list){
this.listAuth=list;
}
// 调度到其他的认证信息
@Override
public boolean authInfo() {
boolean flag=true;
for (Authentication authentication: listAuth){
boolean isOk= authentication.authInfo();
if (!isOk){
flag=false;
break;
}
}
return flag;
}
}
实体类,银行认证时需要用的实体类
public class BankInfo {
private Long id;
private String bankName;
private String bankNo;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setBankNo(String bankNo) {
this.bankNo = bankNo;
}
public String getBankNo() {
return bankNo;
}
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
// 构建器,构建银行实体信息,简化设置实体数据
public static class Builder{
BankInfo bankInfo=new BankInfo();
public Builder(String name,String bankNo,Long id){
bankInfo.setBankName(name);
bankInfo.setBankNo(bankNo);
bankInfo.setId(id);
}
public BankInfo build(){
return bankInfo;
}
}
}
实体类,联系人认证时需要用到的实体类
public class ContactInfo {
private Long id;
private String name;
private String phone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public static class Builder{
ContactInfo contactInfo=new ContactInfo();
public Builder(String name,String phone,Long id){
contactInfo.setName(name);
contactInfo.setPhone(phone);
contactInfo.setId(id);
}
public ContactInfo build(){
return contactInfo;
}
}
}
实体类,个人信息认证时需要用到的实体类
public class PersonInfo {
private Long id;
private String name;
private String idCard;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public static class Builder{
PersonInfo personInfo=new PersonInfo();
public Builder(String name,String idCard,Long id){
personInfo.setName(name);
personInfo.setIdCard(idCard);
personInfo.setId(id);
}
public PersonInfo build(){
return personInfo;
}
}
}
单元测试,将银行认证信息,个人认证信息以及联系人信息传入到认证各个子模块中,然后实例化总认证信息,然后就可以调用到所有的认证方法里了。
public static void main(String[] args) {
Authentication bankAuth=new BankAuth(new BankInfo.Builder("中国银行","122211111",1L).build());
Authentication personAuth=new PersonAuth(new PersonInfo.Builder("杜杜","152188822299222",1L).build());
Authentication contactAuth=new ContactAuth(new ContactInfo.Builder("谢谢","18899991232",2L).build());
List<Authentication> list=new ArrayList();
list.add(bankAuth);
list.add(personAuth);
list.add(contactAuth);
// 调用认证,所有认证都被调度到
Authentication overAllInfo= new OverAllInfoAuth (list);
overAllInfo.authInfo();
}
运行结果,三个方法认证全部都被调度了,并且还拿到了对应的实体数据并打印出来了。