当前位置 博文首页 > 韩超的博客 (hanchao5272):设计模式-外观模式-以瀑布模型软件开

    韩超的博客 (hanchao5272):设计模式-外观模式-以瀑布模型软件开

    作者:[db:作者] 时间:2021-09-05 16:12

    超级链接: Java常用设计模式的实例学习系列-绪论

    参考:《HeadFirst设计模式》


    1.关于外观模式

    外观(facade)模式是一种结构型设计模式。

    外观模式:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

    本文以瀑布模型软件开发为场景来学习外观模式

    • 瀑布模型软件开发过程:制定计划、需求分析、软件设计、程序编写、软件测试和运行维护。
    • 制定计划的主要执行者:产品经理。
    • 需求分析的主要执行者:产品经理。
    • 软件设计的主要执行者:开发经理。
    • 程序编写的主要执行者:开发攻城狮,可能有多人。
    • 软件测试的主要执行者:测试攻城狮,可能有多人。
    • 运行维护的主要执行者:运维攻城狮,可能有多人。

    2.实现方式:外观模式

    这个模式比较简单,直接进行设计模式编码。

    2.1.项目参与者及其技能

    无论是产品经理,还是开发经理,抑或是攻城狮,他们都是项目参与者。

    这些项目参与者都有自己的工作,例如:开发、测试等。他们的工作都是软件开发这件事的一部分。

    参与者抽象:AbstractWorker

    /**
     * <p>打工者</P>
     *
     * @author hanchao
     */
    @AllArgsConstructor
    @Getter
    public abstract class AbstractWorker {
        /**
         * 姓名
         */
        private String name;
    
        /**
         * 职位
         */
        private String job;
    }
    

    参与者实现:产品经理:ProjectManager

    /**
     * <p>产品经理</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class ProjectManager extends AbstractWorker {
        public ProjectManager(String name) {
            super(name, "项目经理");
        }
    
        public void makeProjectPlan() {
            log.info("「{}」({})制定了项目计划...", super.getName(), super.getJob());
        }
    
        public void analysisRequirement() {
            log.info("「{}」({})进行了需求分析...", super.getName(), super.getJob());
        }
    }
    

    参与者实现:开发经理:DevelopManager

    /**
     * <p>开发经理</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class DevelopManager extends AbstractWorker {
        public DevelopManager(String name) {
            super(name, "开发经理");
        }
    
        public void makeDevelopmentPlan() {
            log.info("「{}」({})制定了研发计划...", super.getName(), super.getJob());
        }
    }
    
    

    参与者实现:开发攻城狮:DevelopmentEngineer

    /**
     * <p>开发攻城狮</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class DevelopmentEngineer extends AbstractWorker {
        public DevelopmentEngineer(String name,String job) {
            super(name, job);
        }
    
        public void develop() {
            log.info("「{}」({})开始进行研发...", super.getName(), super.getJob());
        }
    }
    

    参与者实现:测试攻城狮:QualityAssurance

    /**
     * <p>测试攻城狮</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class QualityAssurance extends AbstractWorker {
        public QualityAssurance(String name) {
            super(name, "测试攻城狮");
        }
    
        public void test() {
            log.info("「{}」({})开始进行测试...", super.getName(), super.getJob());
        }
    }
    

    参与者实现:运维攻城狮:Operations

    /**
     * <p>运维攻城狮</P>
     *
     * @author hanchao
     */
    @Slf4j
    public class Operations extends AbstractWorker {
        public Operations(String name) {
            super(name, "运维攻城狮");
        }
    
        public void operationAndMaintenance() {
            log.info("「{}」({})持续运维中...", super.getName(), super.getJob());
        }
    }
    

    2.2.软件开发的外观方法

    无论哪个项目,如果采用相同的开发模型(例如瀑布模型)进行开发,那么其整体步骤是确定的,变化的是参与的人员。

    外观类:Project

    • 定义了外观方法developProject(),其内,调用了一组不同对象的多个接口。
    /**
     * <p>项目开发</P>
     *
     * @author hanchao
     */
    @Slf4j
    @RequiredArgsConstructor
    public class Project {
        /**
         * 项目名称
         */
        @NonNull
        private String name;
    
        /**
         * 产品经理
         */
        @NonNull
        private ProjectManager projectManager;
    
        /**
         * 开发经理
         */
        @NonNull
        private DevelopManager developManager;
    
        /**
         * 开发攻城狮们
         */
        @NonNull
        private List<DevelopmentEngineer> engineerList;
    
        /**
         * 测试攻城狮
         */
        @NonNull
        private List<QualityAssurance> assuranceList;
    
        /**
         * 运维攻城狮
         */
        @NonNull
        private List<Operations> operationsList;
    
        /**
         * 开发过程
         */
        public void developProject() {
            log.info("「{}」项目启动...", name);
            log.info("-----------------------------");
            //指定计划
            projectManager.makeProjectPlan();
    
            //需求分析
            projectManager.analysisRequirement();
    
            //软件设计
            developManager.makeDevelopmentPlan();
    
            //程序编写
            engineerList.forEach(DevelopmentEngineer::develop);
    
            //软件测试
            assuranceList.forEach(QualityAssurance::test);
    
            //运行维护
            operationsList.forEach(Operations::operationAndMaintenance);
    
            log.info("-----------------------------");
            log.info("「{}」项目完成...", name);
        }
    }
    

    2.3.测试代码与结果

    测试代码

    • 无论是哪个项目,因为项目开发流程是固定的,只要开始的时候安排好人员,则项目都会按照一致的流程进行。
    • 客户端无需因为项目的不同,去请求不同的参与者执行不同的接口;客户端只需要调用外观方法即可。
        public static void main(String[] args) {
            //产品经理
            ProjectManager projectManager = new ProjectManager("扫地僧");
            //开发经理
            DevelopManager developManager = new DevelopManager("张三丰");
            //开发攻城狮们
            List<DevelopmentEngineer> engineerList = Lists.newArrayList(
                    new DevelopmentEngineer("令狐冲", "前端开发攻城狮"),
                    new DevelopmentEngineer("张无忌", "后端开发攻城狮")
            );
            //测试攻城狮们
            List<QualityAssurance> assuranceList = Lists.newArrayList(
                    new QualityAssurance("小龙女")
            );
            //运维攻城狮们
            List<Operations> operationsList = Lists.newArrayList(
                new Operations("鸠摩智"),
                new Operations("欧阳锋")
            );
    
            //项目一
            new Project("武林群侠传项目", projectManager, developManager, engineerList, assuranceList, operationsList).developProject();
    
            log.info("=============================");
    
            //项目二
            new Project("入职项目", projectManager, developManager,
                    Collections.singletonList(new DevelopmentEngineer("小虾米", "前端开发攻城狮")),
                    Collections.singletonList(new QualityAssurance("小虾米")),
                    Collections.singletonList(new Operations("小虾米"))).developProject();
        }
    

    测试结果

    2019-07-28 16:16:07,823  INFO - 「武林群侠传项目」项目启动... 
    2019-07-28 16:16:07,828  INFO - ----------------------------- 
    2019-07-28 16:16:07