• Java设计模式----模板方法模式


    抽象是面向对象编程的核心思想,从某种角度来看,抽象,就是把可变的部分和不可变部分分离开来,今天介绍的模板方法模式,体现的就是这样一种思想。总结起来,模板方法模式可以用一句话来概括:以不变应万变


    1.模板方法模式

    模板方法模式(Template Method Pattern),定义了一个算法的骨架,将一些具体步骤的实现推迟到子类中。

    模板方法设计模式的核心思想就是将“可变部分”与“不可变部分”分离,通常,在一个抽象基类中定义模板方法,该方法即算法不可变部分,其中调用了一系列抽象方法,这些可重写的抽象方法即可变部分,由其子类重写。因此,模板方法模式可以在不改变算法结构的情况下,重新调整算法中的某些步骤。

    模版方法模式的UML类图:

    图中,

    templateMethod() 模板方法

    action1,action2 是需要子类重写的抽象方法


    2.代码实现

    假设汽车由一条生产线装备(现实中是多条生产线),这条生产线上有各个机器人,入负责底盘的机器人,负责装配发动机的机器人,负责装配轮胎的机器人,负责装配车身的机器人。很显然,机器人可以抽象出一个类代表机器人这个抽象体,每个具体机器人都负责装配某部件。那么,可以在抽象机器人类中,定义一个模版方法,该方法定义了所有机器人装配零件时的通用步骤(算法),而具体细节由各个机器人实现。

    首先,定义Car类,即汽车,我们的装配对象。 用布尔类型的属性记录是否已装配了相应零件的状态。

    /**
     * 汽车类,装配对象
     */
    class Car {
        private static int count = 0;
        private final int id;
        public Car() {
            id = count++;
        }
        /** 汽车底盘 */
        private boolean chassis = false;
        /** 发动机*/
        private boolean engine = false;
        /** 轮胎 */
        private boolean wheels = false;
        /** 车身 */
        private boolean body = false;
    
        /** 安装底盘*/
        public void setChassis(){
            chassis = true;
        }
        /** 安装发动机*/
        public void setEngine(){
            engine = true;
        }
        /** 安装轮胎*/
        public void setWheels() {
            wheels = true;
        }
        /** 安装车身 */
        public void setBody() {
            body = true;
        }
    
        public String toString() {
            return "car" + id + "( chassis:" + chassis + ", engine:" + engine +
                    ", wheels:" + wheels + ", body:" + body + ")" ;
        }
    }

    定义机器人抽象类,有成员属性Assembler,即装配线的引用,该装配线与本例中的模版方法模式无关。定义了模版方法:assemble(),即装配,该方法中设计了一些具体机器人的共通逻辑,而调用的performance(0,则将具体装配推迟到了子类中。

    /**
     * 机器人抽象类,提供模板方法assemble,以及一系列抽象方法
     */
    abstract class Robot {
        protected Assembler assembler;
    
        public void setAssembler(Assembler assembler) {
            this.assembler = assembler;
        }
    
        /** 模板方法 */
        protected void assemble() {
            System.out.println("开始装配:" + assembler.car);
            performance();
            System.out.println("装配完成:" + assembler.car);
        }
    
        protected abstract void performance();
    }

    各个具体机器人,实现了“可变”的方法performance()

    /**
     * 底盘装配机器人
     */
    class ChassisRobot extends Robot{
    
        @Override
        protected void performance() {
            assembler.car.setChassis();
        }
    }
    
    /**
     * 发动机装配机器人
     */
    class EngineRobot extends Robot {
    
        @Override
        protected void performance() {
            assembler.car.setEngine();
        }
    }
    
    /**
     * 轮胎装配机器人
     */
    class WheelsRobot extends Robot {
        @Override
        protected void performance() {
            assembler.car.setWheels();
        }
    }
    
    /**
     * 车身装配机器人
     */
    class BodyRobot extends Robot {
    
        @Override
        protected void performance() {
            assembler.car.setBody();
        }
    }

    Assembler,为了更好地完成调度和管理

    /**
     * 生产线,调度机器人装配
     */
    class Assembler {
        List<Robot> robots;
        Car car;
        public Assembler(Car car) {
            this.car=  car;
            //注册机器人
            robots = new ArrayList<>();
            robots.add(new ChassisRobot());
            robots.add(new EngineRobot());
            robots.add(new WheelsRobot());
            robots.add(new BodyRobot());
        }
    
        public void run() {
            for (Robot robot : robots) {
                robot.setAssembler(this);
                robot.assemble();
            }
        }
    }

    客户端调用,首先创建Car实体,将其传入生产线Assembler,生产线run起来,即开始装配汽车零件。

    public class TemplateDemo {
    
        public static void main(String[] args) {
            Car car = new Car();
            Assembler assembler = new Assembler(car);
            assembler.run();
        }
    }

    输出结果:

    开始装配:car0( chassis:false, engine:false, wheels:false, body:false)
    装配完成:car0( chassis:true, engine:false, wheels:false, body:false)
    开始装配:car0( chassis:true, engine:false, wheels:false, body:false)
    装配完成:car0( chassis:true, engine:true, wheels:false, body:false)
    开始装配:car0( chassis:true, engine:true, wheels:false, body:false)
    装配完成:car0( chassis:true, engine:true, wheels:true, body:false)
    开始装配:car0( chassis:true, engine:true, wheels:true, body:false)
    装配完成:car0( chassis:true, engine:true, wheels:true, body:true)

    3.总结

    这里再强调一遍,用一句话概括模版方法模式就是:以不变应万变。这其中体现出的是面向对象编程当中最基本和最重要的思想:抽象。模版方法模式通过分离可变部分和不可变部分,实现了代码的解耦,使扩展和维护更加方便,模版方法模式在实际开发中大量应用,尽管很多时候是无意的。我想之所以要学习程序设计模式,并不是为了死记硬背其流程和步骤,应该体会一下各个模式背后的思想精髓,才能对编程这件事情有更加深刻的理解。

  • 相关阅读:
    vue iview 导入excel文件(upload)
    iview table 中用根据不同状态改变颜色(用render)
    vue项目中导出excel表格数据
    iview table 中 render 时间格式化
    微信浏览器的部分特效更接近浏览器IE 9
    ABP 拦截器不工作
    vue + webpack 添加的引用不编译成ES6的问题
    把vue组件添加到body下
    vue+vuex+router实现阻止浏览器回退
    webpack使用vue-moment-libs 在PC微信浏览器下显示空白
  • 原文地址:https://www.cnblogs.com/yxlaisj/p/10479308.html
Copyright © 2020-2023  润新知