美文网首页设计模式
设计模式实践-外观模式

设计模式实践-外观模式

作者: h2coder | 来源:发表于2020-10-19 07:43 被阅读0次

什么是外观模式?什么时候用?

外观模式,也称为门面模式。其实日常生活中,有很多外观模式的影子,例如我们日常工作中,领导层,决定要开发一个直播模块,领导层给中层(部门老大)发出命令,中层则分配到特定的执行层(我们开发)。领导层无需知道下面的人是怎么分配的,谁和谁配合,只要发出命令,验收结果即可。

场景

  • 例如刚完成的直播间模块,用户角色的改变,UI界面上很多部件的状态、样式、点击事件等都需要切换,这篇文章就不一一列举了,不是本文重点,避免跑题。

  • 直播间总共有以下角色:

    1. 普通用户
    2. 上座用户
    3. 房管
    4. 老师(主播)
    5. 禁言用户
    6. 游客
直播间样式.png
  • 可以看到直播间的角色是非常多的,也不排除以后会增加其他角色,例如其他pk、助场老师等。这就涉及到了角色切换,切换的地方又不止一处,有的是由接口调用回调时切换,有的是IM触发而切换等等...那么需要切换的组件大于3个以上,每处都需要写相同的代码,而后续再加组件也需要切换时,就需要每处都要修改,这时就可以使用外观模式来统一分发切换,外部调用方无需知道哪些组件需要进行切换,只需要做要发起切换的动作行为即可。

怎么实现外观模式?

  • Facade,门面接口,对外提供的Api接口。
  • 子系统接口,每个子系统都需要实现。

外观模式实践,统一处理直播间角色改变

如果正常逻辑去编写我们的代码,就会有非常多的if-else,所以每个UI组件我都用状态模式封装了一遍,外部只需要调用切换角色API即可,无需关注内部是怎么切换的,是显示、隐藏还是Remove、Add。而角色改变的时机并不是只有一处,那么调用各个组件的切换方法就会到处都是,为了解决这种情况我们使用外观模式,统一调用外观,外观再分发给每个需要角色切换的组件。

实现步骤

  1. IRoleSwitcher接口,角色切换接口,定义了每种角色的切换方法,这里由于我们的门面和其他组件的操作是一样的,所以合并给一个接口。

  2. Component接口,子系统接口,定义通用组件方法,每个子系统都会自己有一个接口继承它,并提供子系统的特定Api。

  3. IBottomBarComponent,底部栏组件接口,实现了Component接口和IRoleSwitcher接口。

  4. IApplyForSeatComponent,上座按钮组件接口,实现了Component接口和IRoleSwitcher接口。

  5. IToolBoxComponent,辅助工具栏组件接口,实现了Component接口和IRoleSwitcher接口。

  6. IRoleComponent,角色组件,就是我们外观,Facade,负责分发切换事件给上面的3个组件,由于我们门面Api和子系统Api是一致的,所以本身也实现了IRoleSwitcher操作接口。同样实现了Component作为组件使用。(非必须,只是我们的场景比较简单,基本就是分发切换事件,而其他需要不同子系统配合的场景,门面Api一般和子系统是不一样的)

别废话,上代码~

  • Component组件接口和IRoleSwitcher接口。
public interface Component {
}

public interface IRoleSwitcher {
    /**
     * 设置为普通用户角色
     */
    void setNormalUserRole();

    /**
     * 设置为管理员角色
     */
    void setManagerRole();

    /**
     * 设置为上座用户角色
     */
    void setSeatUpRole();

    /**
     * 设置为老师角色
     */
    void setTeacherRole();

    /**
     * 设置为游客角色
     */
    void setVisitorRole();

    /**
     * 设置为游客禁言角色
     */
    void setForbidSpeakRole();
}
  • IBottomBarComponent,底部栏组件接口和实现类
public interface IBottomBarComponent extends Component, IRoleSwitcher {
    //...其他Api方法,不是重点
}

public class BottomBarComponent extends BaseRoomComponent implements IBottomBarComponent {
    @Override
    public void setNormalUserRole() {
        //底部栏切换到普通用户角色样式
        ...
    }

    @Override
    public void setManagerRole() {
        //底部栏切换到普通用户角色样式
        ...
    }

    @Override
    public void setSeatUpRole() {
        //底部栏切换到上座用户角色样式
        ...
    }

    @Override
    public void setTeacherRole() {
        //底部栏切换到老师用户角色样式
        ...
    }

    @Override
    public void setVisitorRole() {
        //底部栏切换到游客角色样式
        ...
    }

    @Override
    public void setForbidSpeakRole() {
        //底部栏切换到禁言用户角色样式
        ...
    }
}
  • IApplyForSeatComponent,上座按钮组件
public interface IApplyForSeatComponent extends Component, IRoleSwitcher {
        //...省略其他Api
}

public class ApplyForSeatComponent extends BaseRoomComponent implements IApplyForSeatComponent {
        //...实现方法和BottomBarComponent是一致的,所以不再列举
}
  • IToolBoxComponent,辅助工具栏组件
public interface IToolBoxComponent extends Component, IRoleSwitcher {
        //...省略其他Api
}

public class ToolBoxComponent extends BaseRoomComponent implements IToolBoxComponent {
        //...实现方法和BottomBarComponent是一致的,所以不再列举
}
  • IRoleComponent,角色组件,中介类
public class RoleComponent extends BaseRoomComponent implements IRoleComponent {
@Override
    public void setNormalUserRole() {
        getComponentProvider().getBottomBarComponent().setNormalUserRole();
        getComponentProvider().getApplyForSeatComponent().setNormalUserRole();
        getComponentProvider().getToolBoxComponent().setNormalUserRole();
    }

    @Override
    public void setManagerRole() {
        getComponentProvider().getBottomBarComponent().setManagerRole();
        getComponentProvider().getApplyForSeatComponent().setManagerRole();
        getComponentProvider().getToolBoxComponent().setManagerRole();
    }

    @Override
    public void setSeatUpRole() {
        getComponentProvider().getBottomBarComponent().setSeatUpRole();
        getComponentProvider().getApplyForSeatComponent().setSeatUpRole();
        getComponentProvider().getToolBoxComponent().setSeatUpRole();
    }

    @Override
    public void setTeacherRole() {
        getComponentProvider().getBottomBarComponent().setTeacherRole();
        getComponentProvider().getApplyForSeatComponent().setTeacherRole();
        getComponentProvider().getToolBoxComponent().setTeacherRole();
    }

    @Override
    public void setVisitorRole() {
        getComponentProvider().getBottomBarComponent().setVisitorRole();
        getComponentProvider().getApplyForSeatComponent().setVisitorRole();
        getComponentProvider().getToolBoxComponent().setVisitorRole();
    }

    @Override
    public void setForbidSpeakRole() {
        getComponentProvider().getBottomBarComponent().setForbidSpeakRole();
        getComponentProvider().getApplyForSeatComponent().setForbidSpeakRole();
        getComponentProvider().getToolBoxComponent().setForbidSpeakRole();
    }
}
  • 切换调用处调用
mDataStore = getDataStore();
    //监听房间信息改变切换角色。
    mDataStore.getLiveRoomViewModel().getRoomInformationLiveData().observe(getLifecycleOwner(), new Observer<RoomInformationModel>() {
    @Override
    public void onChanged(@Nullable RoomInformationModel roomInformationModel) {
        if (roomInformationModel == null) {
            return;
        }
        IMRoomInfoModel roomInfoModel = roomInformationModel.getRoomInfo();
        IMSendUserModel currentUser = mDataStore.getLiveRoomViewModel().getCurrentUserLiveData().getValue();
        if (currentUser == null) {
            return;
        }
        //这里简单期间,省略了决定角色的生成,决定后通知其他组件切换样式
        IRoleComponent roleComponent = getComponentProvider().getRoleComponent();
        //老师角色
        if (currentUser.isTeacher()) {
            roleComponent.setTeacherRole();
        } else if (currentUser.isNormalUser()) {
            //普通用户角色
            roleComponent.setNormalUserRole();
        } else if (currentUser.isSeatUpUser()) {
            //上座用户角色
            roleComponent.setSeatUpRole();
        } else if (currentUser.VisitorRole()) {
            //游客角色
            roleComponent.setVisitorRole();
        } else if (currentUser.isForbidSpeakUser()) {
            //禁言用户角色
            roleComponent.setForbidSpeakRole();
        }
    }
});

总结

  • 外观模式的优点:提供统一入口方法给外部,隐藏内部子系统的细节。

  • 外观模式的缺点,外观类没有遵循开闭原则,当我们的业务变更时,可能就需要修改外观类,增加新的逻辑和子系统类。

相关文章

  • 设计模式实践-外观模式

    什么是外观模式?什么时候用? 外观模式,也称为门面模式。其实日常生活中,有很多外观模式的影子,例如我们日常工作中,...

  • Android设计模式——外观模式(七大结构型)

    1.外观模式介绍 外观模式(Facade Pattern),是七大结构型设计模式之一。 外观模式运...

  • 设计模式[9]-外观模式-Facade Pattern

    1. 外观模式 外观模式(Facade Pattern),又称为门面模式,是非常常用的结构性设计模式。外观模式使得...

  • java设计模式-外观模式(Facade)

    外观模式,属于结构性模式。属于设计模式里面比较简单的设计模式,本人认为是最简单的设计模式。 所谓外观,就是我们能看...

  • 了解外观模式

    java 设计模式 ------外观模式 Java中一共有23种设计模式,每种设计模式各有特...

  • 设计模式之-4.外观模式

    每看一次设计模式,感觉每一个设计模式看起来是那么简单,对于外观模式我的理解就是外观模式:外观模式,这个名字起得不怎...

  • 设计模式详解——外观模式

    本篇文章介绍一种设计模式——外观模式。本篇文章内容参考《JAVA与模式》之门面模式,外观模式,深入浅出外观模式(二...

  • 外观模式(Facede)

    本文参考自: 《JAVA设计模式》之外观模式(Facade) 1. 作用 外观模式也叫门面模式,门面模式是对象的结...

  • 设计模式---外观模式

    1、外观模式(Facade):也叫门面模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个...

  • 设计模式——外观模式

    阎宏博士的《JAVA与模式》一书中开头是这样描述外观(Facade)模式的:门面模式是对象的结构模式,外部与一个子...

网友评论

    本文标题:设计模式实践-外观模式

    本文链接:https://www.haomeiwen.com/subject/skompktx.html