Java代码设计模式讲解二十三种设计模式(六)

简介: Java代码设计模式讲解二十三种设计模式

2.10 模板模式

(1)概念

模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨

架,并允许子类为一个或者多个步骤提供实现。模板方法使得子类可以在不改变算法结

构的情况下,重新定义算法的某些步骤,属于行为性设计模式。

(2)适用场景

1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。

3、通常,在微服务架构中一般会建立一个common的module,里面抽取公共的类,然后其他的module来是这个module的子module

(3)代码示例

整体的类图

我们通常上网课看视频,通常网课的步骤是发布预习资料–>制作课件 PPT–>在线直播–> 提 交 课 堂 笔 记 --> 提 交 源 码 --> 布 置 作 业 --> 检 查 作 业 。

首先建立一个抽象类NetworkCourse

  • NetworkCourse 类
package com.alibaba.design.templatemethodpattern.course;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/29-19:50
 */
public  abstract class NetworkCourse {
    public final void createCourse(){
        //1、发布预习资料
        this.postPreResource();
        //2、制作PPT课件
        this.createPPT();
        //3、在线直播
        this.liveVideo();
        //4、提交课件、课堂笔记
        this.postNote();
        //5、提交源码
        this.postSource();
        //6、布置作业,有些课是没有作业,有些课是有作业的
        //如果有作业的话,检查作业,如果没作业,完成了
        if(needHomeWork()){
            checkHomeWork();
        }
    }
    abstract void checkHomeWork();
    //钩子方法:实现流程的微调
    protected boolean needHomeWork(){return false;}
    final void postSource(){
        System.out.println("提交源代码");
    }
    final void postNote(){
        System.out.println("提交课件和笔记");
    }
    final void liveVideo(){
        System.out.println("直播授课");
    }
    final void createPPT(){
        System.out.println("创建备课PPT");
    }
    final void postPreResource(){
        System.out.println("分发预习资料");
    }
}

上述的钩子方法是设计可以进行流程的微调的,因为通常有些指标不是必须的,比如布置作业,有时候布置了有时候不用布置,因此可以这样来设计。

  • JavaCourse类
package com.alibaba.design.templatemethodpattern.course;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/29-19:51
 */
public class JavaCourse extends NetworkCourse{
    @Override
    void checkHomeWork() {
        System.out.println("检查java的作业");
    }
}
  • PythonCourse类
package com.alibaba.design.templatemethodpattern.course;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/29-19:52
 */
public class PythonCourse extends NetworkCourse {
    private boolean needHomeworkFlag = false;
    public PythonCourse(boolean needHomeworkFlag){
        this.needHomeworkFlag = needHomeworkFlag;
    }
    @Override
    void checkHomeWork() {
        System.out.println("检查Python的作业");
    }
    @Override
    protected boolean needHomeWork() {
        return  this.needHomeworkFlag;
    }
}
  • 客户端测试类
package com.alibaba.design.templatemethodpattern.test;
import com.alibaba.design.templatemethodpattern.course.JavaCourse;
import com.alibaba.design.templatemethodpattern.course.NetworkCourse;
import com.alibaba.design.templatemethodpattern.course.PythonCourse;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/29-19:53
 */
public class NetworkCourseTest {
    public static void main(String[] args) {
        System.out.println("---Java架构师课程---");
        NetworkCourse javaCourse = new JavaCourse();
        javaCourse.createCourse();
        System.out.println("---Python课程---");
        NetworkCourse pythonCourse = new PythonCourse(true);
        pythonCourse.createCourse();
    }
}

(4)模板模式在源码中的体现

在AbstractList类中的get方法就是一个抽象的方法

在AbstractList类的继承类中的ArrayList中对get方法进行了重写

(5)模板模式的优缺点

  • 优点:
    1、利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
    2、将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
    3、把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,
    符合开闭原则。
  • 缺点:
    1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
    2、类数量的增加,间接地增加了系统实现的复杂度。
    3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。

2.11 空对象模式 (不属于二十三中设计模式中的,这里是扩充一下)

(1)概念

在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。

在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。

(2)适用场景

满足下列条件时可以使用空对象模式

  • 一个对象需要一个协作对象,但并无具体的协作对象
  • 协作对象不需要做任何事情
  • 需要大量对空值进行判断的时候;

(3)代码示例

我们将创建一个定义操作(在这里,是客户的名称)的 AbstractCustomer 抽象类,和扩展了 AbstractCustomer 类的实体类。工厂类 CustomerFactory 基于客户传递的名字来返回 RealCustomerNullCustomer 对象。

NullPatternDemo,我们的演示类使用 CustomerFactory 来演示空对象模式的用法。

创建一个抽象类。

package com.alibaba.design.nullobjectpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:14
 */
public abstract class AbstractCustomer {
    protected String name;
    public abstract boolean isNil();
    public abstract String getName();
}

创建扩展了上述类的实体类。

package com.alibaba.design.nullobjectpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:16
 */
public class NullCustomer extends AbstractCustomer {
    @Override
    public boolean isNil() {
        return true;
    }
    @Override
    public String getName() {
        return "Not Available in Customer Database";
    }
}
package com.alibaba.design.nullobjectpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:15
 */
public class RealCustomer extends AbstractCustomer {
    public RealCustomer(String name) {
        this.name = name;
    }
    @Override
    public boolean isNil() {
        return false;
    }
    @Override
    public String getName() {
        return name;
    }
}

创建 CustomerFactory 类。

package com.alibaba.design.nullobjectpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:17
 */
public class CustomerFactory {
    public static final String[] names = {"Rob", "Joe", "Julie"};
    public static AbstractCustomer getCustomer(String name){
        for (int i = 0; i < names.length; i++) {
            if (names[i].equalsIgnoreCase(name)){
                return new RealCustomer(name);
            }
        }
        return new NullCustomer();
    }
}

客户端测试类

package com.alibaba.design.nullobjectpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:17
 */
public class NullPatternDemo {
    public static void main(String[] args) {
        AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob");
        AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob");
        AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie");
        AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura");
        System.out.println("Customers");
        System.out.println(customer1.getName());
        System.out.println(customer2.getName());
        System.out.println(customer3.getName());
        System.out.println(customer4.getName());
    }
}

输出结果:

(4)该模式在源码中的体现

commons-lang3 jar包里面的StringUtils

包含了isNotEmpty()就是对String类型的对象的空值判断,我们通常可以用他对字符串进行空值判断处理

(5)空对象模式的优缺点

  • 优点
    可以加强系统的稳固性,能有效防止空指针报错对整个系统的影响;
    不依赖客户端便可以保证系统的稳定性;
  • 缺点
    需要编写较多的代码来实现空值的判断,从某种方面来说不划算;

2.12 访问者模式

(1)概念

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

主要解决:稳定的数据结构和易变的操作耦合问题。

何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

如何解决:在被访问的类里面加一个对外提供接待访问者的接口。

关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

(2)适用场景

1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

(3)代码示例

我们将创建一个定义接受操作的 ComputerPart 接口。KeyboardMouseMonitorComputer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。

VisitorPatternDemo,我们的演示类使用 ComputerComputerPartVisitor 类来演示访问者模式的用法。

定义一个表示元素的接口。

  • ComputerPart
package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:54
 */
public interface ComputerPart {
    public void accept(ComputerPartVisitor computerPartVisitor);
}

定义一个表示访问者的接口。

  • ComputerPartVisitor
package com.alibaba.design.visitorpattern;
import com.alibaba.design.visitorpattern.Mouse;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:54
 */
public interface ComputerPartVisitor {
    public void visit(Computer computer);
    public void visit(Mouse mouse);
    public void visit(Keyboard keyboard);
    public void visit(Monitor monitor);
}

创建扩展了ComputerPart 的实体类。

  • Computer
package com.alibaba.design.visitorpattern;
import com.alibaba.design.visitorpattern.Mouse;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:56
 */
public class Computer implements ComputerPart  {
    ComputerPart[] parts;
    public Computer(){
        parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
    }
    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        for (int i = 0; i < parts.length; i++) {
            parts[i].accept(computerPartVisitor);
        }
        computerPartVisitor.visit(this);
    }
}
  • Keyboard
package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-8:55
 */
public class Keyboard implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}
  • Monitor
package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-9:05
 */
public class Monitor implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}
  • Mouse
package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-9:05
 */
public class Mouse implements ComputerPart {
    @Override
    public void accept(ComputerPartVisitor computerPartVisitor) {
        computerPartVisitor.visit(this);
    }
}

创建实现了上述类的实体访问者。

  • ComputerPartDisplayVisitor
package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-9:06
 */
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
    @Override
    public void visit(Computer computer) {
        System.out.println("Displaying Computer.");
    }
    @Override
    public void visit(Mouse mouse) {
        System.out.println("Displaying Mouse.");
    }
    @Override
    public void visit(Keyboard keyboard) {
        System.out.println("Displaying Keyboard.");
    }
    @Override
    public void visit(Monitor monitor) {
        System.out.println("Displaying Monitor");
    }
}

客户端测试类

package com.alibaba.design.visitorpattern;
/**
 * @author zhouyanxiang
 * @create 2020-08-2020/8/2-9:08
 */
public class VisitorPatternDemo {
    public static void main(String[] args) {
        ComputerPart computer = new Computer();
        computer.accept(new ComputerPartDisplayVisitor());
    }
}

输出结果:

(4)该模式在源码中的体现

在Spring中的应用:

它的具体实现都交给了valueResolver来实现

方法visitBeanDefinition实现了不同的visi方法t来对相同的数据进行不同的处理

(5)访问者模式的优缺点

优点:

1、符合单一职责原则。

2、优秀的扩展性。

3、灵活性。

缺点:

1、具体元素对访问者公布细节,违反了迪米特原则。

2、具体元素变更比较困难。

3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

相关文章
|
5天前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
7天前
|
设计模式 算法 数据库连接
PHP中的设计模式:提高代码的可维护性与扩展性
设计模式在PHP开发中至关重要,如单例模式确保类仅有一个实例并提供全局访问点,适用于管理数据库连接或日志记录。工厂模式封装对象创建过程,降低系统耦合度;策略模式定义算法系列并使其可互换,便于实现不同算法间的切换。合理选择设计模式需基于需求分析,考虑系统架构,并通过测试驱动开发验证有效性,确保团队协作一致性和代码持续优化。设计模式能显著提升代码质量,解决开发中的设计难题。
24 8
|
5天前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
17 5
|
7天前
|
Java API 开发者
探索Java中的Lambda表达式:简洁与强大的代码实践
本文深入探讨Java中Lambda表达式的定义、用法及优势,通过实例展示其如何简化代码、提升可读性,并强调在使用中需注意的兼容性和效率问题。Lambda作为Java 8的亮点功能,不仅优化了集合操作,还促进了函数式编程范式的应用,为开发者提供了更灵活的编码方式。
|
3天前
|
Java 开发者
探索Java中的Lambda表达式:简化你的代码之旅##
【8月更文挑战第62天】 Java 8的发布为开发者带来了诸多新特性,其中最引人注目的无疑是Lambda表达式。这一特性不仅让代码变得更加简洁,还极大地提升了开发的效率。本文将通过实际示例,展示如何利用Lambda表达式来优化我们的代码结构,同时探讨其背后的工作原理和性能考量。 ##
|
4天前
|
设计模式 算法 PHP
PHP中的设计模式:提升代码的灵活性与可维护性
在本文中,我们将深入探讨PHP编程语言中的一种重要概念——设计模式。设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它代表了最佳的实践,被有经验的面向对象的软件开发人员所采用。本文将通过具体的实例,展示如何在PHP项目中应用设计模式,以提高代码的灵活性和可维护性。无论你是PHP初学者还是经验丰富的开发者,都能从中获得有价值的见解。
|
6天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入探索与实践在软件开发的广袤天地中,PHP以其独特的魅力和强大的功能,成为无数开发者手中的得力工具。而在这条充满挑战与机遇的征途上,设计模式犹如一盏明灯,指引着我们穿越代码的迷雾,编写出更加高效、灵活且易于维护的程序。今天,就让我们聚焦于设计模式中的璀璨明珠——策略模式,深入探讨其在PHP中的实现方法及其实际应用价值。
策略模式,这一设计模式的核心在于它为软件设计带来了一种全新的视角和方法。它允许我们在运行时根据不同情况选择最适合的解决方案,从而极大地提高了程序的灵活性和可扩展性。在PHP这门广泛应用的编程语言中,策略模式同样大放异彩,为开发者们提供了丰富的创作空间。本文将从策略模式的基本概念入手,逐步深入到PHP中的实现细节,并通过一个具体的实例来展示其在实际项目中的应用效果。我们还将探讨策略模式的优势以及在实际应用中可能遇到的挑战和解决方案,为PHP开发者提供一份宝贵的参考。
|
6天前
|
Java API 开发者
探索Java中的Lambda表达式:简化代码,提升效率
【9月更文挑战第27天】在Java 8中引入的Lambda表达式为编程带来了革命性的变化。通过简洁的语法和强大的功能,它不仅简化了代码编写过程,还显著提升了程序的执行效率。本文将深入探讨Lambda表达式的本质、用法和优势,并结合实例演示其在实际开发中的应用。无论你是Java新手还是资深开发者,都能从中获得启发,优化你的代码设计。
|
5天前
|
设计模式 存储 数据库连接
探索PHP中的设计模式:提高代码的可维护性与扩展性
本文将深入探讨PHP中常用的设计模式,包括单例模式、工厂模式和观察者模式。通过具体的代码示例,展示如何在实际项目中应用这些设计模式,以提高代码的可维护性与扩展性。无论你是PHP初学者还是有一定经验的开发者,都可以通过本文的学习,提升你的编程技巧和项目架构能力。
|
7天前
|
Java Linux Python
Linux环境下 代码java调用python出错
Linux环境下 代码java调用python出错
21 3
下一篇
无影云桌面