• 设计模式--模板方法&外观模式


    模板方法模式

    场景:需使用代码方式实现,考完试后,将各个学生的试卷及答案誊抄一份。

    假如有两个学生的试卷誊抄完毕.

    // 学生A
    public class TestPaperA {
        // 试题1
        public void testQuestion1() {
            System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 A");
        }
        // 试题2
        public void testQuestion2() {
            System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 A");
        }
        // 试题3
        public void testQuestion3() {
            System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 A");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    // 学生B
    public class TestPaperB {
        // 试题1
        public void testQuestion1() {
            System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 B");
        }
        // 试题2
        public void testQuestion2() {
            System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 B");
        }
        // 试题3
        public void testQuestion3() {
            System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 B");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 客户端
    System.out.println("学生A的试卷");
    TestPaperA a = new TestPaperA();
    a.testQuestion1();
    a.testQuestion2();
    a.testQuestion3();
    
    System.out.println("学生B的试卷");
    TestPaperB b = new TestPaperB();
    b.testQuestion1();
    b.testQuestion2();
    b.testQuestion3();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    一眼看出,很多重复的代码,直接进行提炼抽离。此例中,试卷都是一样的,而答案是不同的,我们直接将重复的代码提炼,然后学生去继承它即可。

    • 试卷类
    // 试卷类
    public abstract class TestPaper { 
        // 3道题的答案
        protected abstract String answer1();
        protected abstract String answer2();
        protected abstract String answer3();
    
        // 试题1
        public void testQuestion1() {
            System.out.println("问题一:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 " + answer1());
        }
        // 试题2
        public void testQuestion2() {
            System.out.println("问题二:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 " + answer2());
        }
        // 试题3
        public void testQuestion3() {
            System.out.println("问题三:XXXXXXXX[] A.xx B.xx C.xx D.xx ");
            System.out.println("答案 " + answer3());
        }  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    学生类只需要继承它,然后填写自己的答案即可。因为父类已经建立好了所有重复的模板

    // 学生A
    public class TestPaperA extends TestPaper{
        @Override
        protected String answer1() {
            return "A";
        }
        @Override
        protected String answer2() {
            return "A";
        }
        @Override
        protected String answer3() {
            return "A";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 客户端
    System.out.println("学生A的试卷");
    TestPaper a = new TestPaperA();
    a.testQuestion1();
    a.testQuestion2();
    a.testQuestion3();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    那么上述的例子中,用的一种设计模式就是模板方法模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

    结构图及代码示例如下:

    在这里插入图片描述

    public abstract class AbstractClass {
        
        // 模板方法(所有重复的代码都放入这里)
        public void templateMethod() {
            ...
        }
        
        // 子类的特定实现
        public abstract void primitiveOperation1();
        public abstract void primitiveOperation2();
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 子类
    public class ConcreteClassA extends AbstractClass {
        @Override
        public void primitiveOperation1() {
            System.out.println("A类具体实现一");
        }
    
        @Override
        public void primitiveOperation2() {
            System.out.println("A类具体实现二");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    模板方法是通过把不变行为搬到父类(超类),去除子类中重复代码来体现它的优势。

    模板方法是提供了一个代码复用平台。

    当不变的和可变行为在方法的实现中混合在一起的时候,不变行为就会在类中重复出现。我们通过模板方法将这些行为搬移到单一的地方,这样帮助子类摆脱重复的不变行为的纠缠。

    外观模式

    以一个股票买卖的例子来理解一下,现在有股票、国债、房产,买入卖出代码如下:

    • 股票
    // 股票1
    public class Stock1 {
        public void buy() {
            System.out.println("股票1买入");
        }
        public void sell() {
            System.out.println("股票1卖出");
        }
    }
    // 股票2
    class Stock2 {
        public void buy() {
            System.out.println("股票2买入");
        }
        public void sell() {
            System.out.println("股票2卖出");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 国债、房产
    // 国债1
    public class NationalDebt1 {
        public void buy() {
            System.out.println("国债买入");
        }
        public void sell() {
            System.out.println("国债卖出");
        }
    }
    
    // 房产
    class Realty1 {
        public void buy() {
            System.out.println("房产买入");
        }
        public void sell() {
            System.out.println("房产卖出");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 客户端
    Stock1 stock1 = new Stock1();
    Stock2 stock2 = new Stock2();
    NationalDebt1 nd1 = new NationalDebt1();
    Realty1 rt1 = new Realty1();
    
    // 买入
    stock1.buy();
    stock2.buy();
    nd1.buy();
    rt1.buy();
    
    // 卖出
    stock1.sell();
    stock2.sell();
    nd1.sell();
    rt1.sell();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    外观模式

    增加一个基金类,结构图

    在这里插入图片描述

    • 基金类代码
    public class Fund {
        Stock1 stock1;
        Stock2 stock2;
        NationalDebt1 nd1;
        Realty1 rt1;
        public Fund() {
            stock1 = new Stock1();
            stock2 = new Stock2();
            nd1 = new NationalDebt1();
            rt1 = new Realty1();
        }
        public void buyFund() {
            stock1.buy();
            stock2.buy();
            nd1.buy();
            rt1.buy();
        }
        public void sellFund() {
            stock1.sell();
            stock2.sell();
            nd1.sell();
            rt1.sell();
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 客户端
    Fund fund = new Fund();
    fund.buyFund();
    
    fund.sellFund();
    
    • 1
    • 2
    • 3
    • 4

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

    首先在设计阶段,应该有意识将不同的两个层进行分离。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观模式可以提供一个简单的接口减少它们之间的依赖。

    还可以在新系统中使用外观模式,创建一个Facade类(外观模式类),来提供设计粗糙或高复杂度的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互完成复杂的工作。

  • 相关阅读:
    Kubernetes(k3s)基础学习(三) -- Deployment、Service、Ingress
    js实现一个数据结构——栈
    找到实现虚实结合的正确的方式和方法,并且让区块链的功能和作用得到最大地发挥
    [附源码]Python计算机毕业设计Django基于vuejs的爱宠用品销售app
    requestAnimationFrame实现vue虚拟滚动插件
    SpringCloud - Spring Cloud Netflix 之 Hystrix ;turbine(十)
    Nginx实战:故障处理_后端服务正常,nginx偶发502(Bad Gateway)
    虚拟机Ubuntu 无法打开表格
    javascript的深浅拷贝
    C++ 14:继承构造顺序,static继承问题,继承顺序问题,同名隐藏,菱形继承,final关键字
  • 原文地址:https://blog.csdn.net/weixin_45248492/article/details/134474845