设计模式之组合模式

本文通过实例展示了组合模式在服务类中的应用,解释了如何创建一个能够处理单个对象和对象集合的短信服务。组合模式使得调用者可以方便地选择不同的发送方式,如默认的sms或特定的移动、联通、电信服务。此外,通过递归方法,可以从根节点获取到树形结构中的任意子服务,实现了灵活的消息发送选择。文章还探讨了如何通过工厂方法初始化服务并构建多级组合结构,形成一个树形服务网络。
摘要由CSDN通过智能技术生成

顾名思义,组合模式允许以相同的方式处理单个对象和对象的组合体

也就是说这个组合类可以处理单个的对象,也可以处理对象的集合。

单节点组合

在这里插入图片描述

如上图所示,定义了一个工厂,产生消息对外的一个类,用于外部调用。

定义一个抽象类(SenderService),用于规范一些操作。

SmsService这个类才是应用了组合的类,
在这里插入图片描述

这里面最重要的是这个List , 自己添加自己?

/**
 * @author lw
 * @date 2022/3/29 0029
 * @description 短信服务
 */
public class SmsService extends SenderService{

    //有这个list才叫组合
    private List<SenderService> senderServices = new ArrayList<>();

    public SmsService(String sendType) {
        super(sendType);
    }

    @Override
    public void send() {
        System.out.println("SmsService.send()--->"+this.sendType);
    }

    @Override
    void add(SenderService senderService) {
        this.senderServices.add(senderService);
    }

    @Override
    SenderService getService(String sendType) {
        for (SenderService senderService : this.senderServices) {
            if(sendType.equals(senderService.sendType)){
                return senderService;
            }
        }
        return null;
    }
}

这个代码和装饰器模式的AbstractSenderService对比会发现,AbstractSenderService中List是添加的其他类,而组合是自己加自己。

光这个对象是可以给外界调用,也你可以New出来,但是这体现不了List这个属性的作用。

用一个工厂初始化这个对象,内置一些组合数据。

/**
 * @author lw
 * @date 2022/3/30 0030
 * @description
 */
public class SenderFactory {

    public static SenderService produceSender(){
        SenderService senderService = new SmsService("sms");
        SenderService yiDongService = new SmsService("sms-yidong");
        SenderService lianTongService = new SmsService("sms-liantong");
        SenderService dianXinService = new SmsService("sms-dianxin");

        senderService.add(yiDongService);
        senderService.add(lianTongService);
        senderService.add(dianXinService);

        return senderService;
    }
}

返回的是sms这个最大的信息,这样调用者就可以访问里面的List。

调用者

SenderService senderService = SenderFactory.produceSender();
senderService.send();

SenderService yidongService = senderService.getService("sms-yidong");
yidongService.send();

//运行后输出
SmsService.send()--->sms
SmsService.send()--->sms-yidong

通过输出可以发现,他可以选择默认的sms发送方式,也可以使用移动方式发送。

多节点组合

public static SenderService produceSender(){
        SenderService senderService = new SmsService("sms");
        SenderService yiDongService = new SmsService("sms-yidong");
        SenderService lianTongService = new SmsService("sms-liantong");
        SenderService dianXinService = new SmsService("sms-dianxin");

        senderService.add(yiDongService);
        senderService.add(lianTongService);
        senderService.add(dianXinService);

        SenderService yiDong5GService = new SmsService("sms-yidong-5g");
        SenderService yiDong4GService = new SmsService("sms-yidong-4g");
        SenderService yiDong3GService = new SmsService("sms-yidong-3g");

        yiDongService.add(yiDong5GService);
        yiDongService.add(yiDong4GService);
        yiDongService.add(yiDong3GService);

        return senderService;
}

修改工厂类,继续在sms-yidong下添加5g,4g,3g的发送方式。
在这里插入图片描述

最后如上图所示,变成一个树形结构,所以组合也常用来存储组织信息。

调用者

SenderService senderService = SenderFactory.produceSender();
senderService.send();

SenderService yidongService = senderService.getService("sms-yidong");
yidongService.send();

SenderService yidong5GService = yidongService.getService("sms-yidong-5g");
yidong5GService.send();

//运行后输出
SmsService.send()--->sms
SmsService.send()--->sms-yidong
SmsService.send()--->sms-yidong-5g

当然也可以把获取List中Service写成一个递归,这样就可以一直遍历获取到叶子节点。

@Override
    SenderService getService(String sendType) {
        for (SenderService senderService : this.senderServices) {
            if(sendType.equals(senderService.sendType)){
                return senderService;
            }else{
                SenderService service = senderService.getService(sendType);
                if(service!=null) return service;
            }
        }
        return null;
    }


//调用处就可以直接通过根节点获取,而不需要知道内部树形长什么样子。
SenderService yidong5GService = senderService.getService("sms-yidong-5g");
yidong5GService.send();

在这里插入图片描述

这就是这个递归栈,有中止符号,一层层循环。

总结

记住:自己添加自己就是一个组合。

我写的最多的是Service,所以我也一般会应用到Service上,我看了其他人的设计模式博客和书,还有视频。

更多的是用一个个DTO来举例,其实在工作中DTO一般会简单定义,而不会太复杂,最多就是设计一个树形结构保存组织信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值