Java设计模式概述

设计模式(Design pattern)是软件开发人员在软件开发过程中面临的一般问题的解决方案模板,这些模板是经过相当长的一段时间的试验和错误总结出来的。 为什么要使用设计模式? 使用设计模式是为了重用代码、提高代码的可读性和可靠性。 在项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案。 常见的设计模式分为三大类:创建型模式、结构型模式和行为型模式。

设计模式的六大原则

1、开闭原则(Open Close Principle)

开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3、依赖倒转原则(Dependence Inversion Principle)

这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

5、迪米特法则,又称最少知道原则(Demeter Principle)

最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

创建型模式(Creational Patterns)

创建型模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

  1. 单例模式(Singleton Pattern)

    • 适用场景:需要确保某一个类只有一个实例,且自行实例化并向整个系统提供这个实例。
    • 示例:数据库连接池、配置文件读取类。
  2. 工厂方法模式(Factory Method Pattern)

    • 适用场景:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法使一个类的实例化延迟到其子类。
    • 示例:日志记录器、读取不同类型文件的解析器。
  3. 抽象工厂模式(Abstract Factory Pattern)

    • 适用场景:提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
    • 示例:GUI工具包中的按钮、文本框、菜单等。
  4. 建造者模式(Builder Pattern)

    • 适用场景:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    • 示例:构建复杂对象如文档、计算机硬件配置。
  5. 原型模式(Prototype Pattern)

    • 适用场景:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    • 示例:对象复制、需要大量相似对象的创建。

结构型模式(Structural Patterns)

结构型模式设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

  1. 适配器模式(Adapter Pattern)

    • 适用场景:将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
    • 示例:旧系统与新系统的集成。
  2. 桥接模式(Bridge Pattern)

    • 适用场景:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
    • 示例:图形绘制程序中的形状和颜色分离。
  3. 组合模式(Composite Pattern)

    • 适用场景:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
    • 示例:文件系统中的文件和文件夹。
  4. 装饰器模式(Decorator Pattern)

    • 适用场景:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
    • 示例:流处理中的BufferedReader和BufferedWriter。
  5. 外观模式(Facade Pattern)

    • 适用场景:为子系统中的一组接口提供一个一致的界面,使得子系统更加容易使用。
    • 示例:简化复杂系统的接口,如简化的数据库接口。
  6. 享元模式(Flyweight Pattern)

    • 适用场景:运用共享技术有效地支持大量细粒度对象的复用。
    • 示例:文本编辑器中的字符对象管理。
  7. 代理模式(Proxy Pattern)

    • 适用场景:为其他对象提供一种代理以控制对这个对象的访问。
    • 示例:虚拟代理、远程代理、保护代理。

行为型模式(Behavioral Patterns)

行为型设计模式特别关注对象之间的通信。

  1. 责任链模式(Chain of Responsibility Pattern)

    • 适用场景:为请求创建一个接收对象的链,这样多个对象都有机会处理请求,避免请求的发送者和接收者之间的耦合。
    • 示例:事务处理中的审批流程。
  2. 命令模式(Command Pattern)

    • 适用场景:将请求封装成对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
    • 示例:菜单命令、操作日志、撤销操作。
  3. 解释器模式(Interpreter Pattern)

    • 适用场景:给定一种语言,定义它的文法表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
    • 示例:编译器、正则表达式处理。
  4. 迭代器模式(Iterator Pattern)

    • 适用场景:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
    • 示例:遍历集合对象,如列表、栈、队列等。
  5. 中介者模式(Mediator Pattern)

    • 适用场景:用一个中介对象来封装一系列对象的交互,使得这些对象不需要显式地相互引用,从而使它们可以松散耦合。
    • 示例:聊天室中的消息传递。
  6. 备忘录模式(Memento Pattern)

    • 适用场景:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
    • 示例:撤销功能、历史记录。
  7. 观察者模式(Observer Pattern)

    • 适用场景:定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
    • 示例:事件监听机制。
  8. 状态模式(State Pattern)

    • 适用场景:允许对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
    • 示例:状态机实现、界面导航。
  9. 策略模式(Strategy Pattern)

    • 适用场景:定义一系列算法,把它们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。
    • 示例:各种排序算法、支付方式选择。
  10. 模板方法模式(Template Method Pattern)

    • 适用场景:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
    • 示例:数据处理中的标准处理流程。
  11. 访问者模式(Visitor Pattern)

    • 适用场景:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
    • 示例:对象结构如文件系统中的文件和文件夹,编译器中的语法树。

创建型模式

工厂模式(Factory Pattern)

问题背景

假设你正在开发一款物流管理应用。 最初版本只能处理卡车运输, 因此大部分代码都在位于名为 卡车的类中。一段时间后, 这款应用变得极受欢迎,同时 你每天都能收到十几次来自海运公司的请求, 希望应用能够支持海上物流功能。 这可是个好消息。 但是代码问题该如何处理呢?目前, 大部分代码都与 卡车类相关。 在程序中添加 轮船类需要修改全部代码。 更糟糕的是, 如果你以后需要在程序中支持另外一种运输方式, 很可能需要再次对这些代码进行大幅修改。 最后, 你将不得不编写繁复的代码, 根据不同的运输对象类, 在应用中进行不同的处理。

解决方案

工厂方法模式建议使用特殊的_工厂_方法代替对于对象构造函数的直接调用 (即使用 new运算符)。 不用担心, 对象仍将通过 new运算符创建, 只是该运算符改在工厂方法中调用罢了。 工厂方法返回的对象通常被称作 “产品”。

image.png
乍看之下, 这种更改可能毫无意义: 我们只是改变了程序中调用构造函数的位置而已。 但是, 仔细想一下, 现在你可以在子类中重写工厂方法, 从而改变其创建产品的类型。 但有一点需要注意:仅当这些产品具有共同的基类或者接口时, 子类才能返回不同类型的产品, 同时基类中的工厂方法还应将其返回类型声明为这一共有接口。
image.png
举例来说, ​ 卡车Truck和 轮船Ship类都必须实现 运输Transport接口, 该接口声明了一个名为 deliver交付的方法。 每个类都将以不同的方式实现该方法: 卡车走陆路交付货物, 轮船走海路交付货物。 ​ 陆路运输Road­Logistics类中的工厂方法返回卡车对象, 而 海路运输Sea­Logistics类则返回轮船对象。

工厂方法模式代码实现

// 工厂方法模式
package com.lin.factorypattern;

public class FactoryMethodTest {
    public static void main(String[] args) {
        // 假设有4个订单,分别为卡车运输、卡车加速运输、海陆运输、海陆加速运输
        Factory factory  = new TruckFactory();
        factory.deliver();

        Factory factory2  = new ShipFactory();
        factory.deliver();

        Factory factory3  = new TruckFactory();
        factory.speedDeliver();

        Factory factory4  = new ShipFactory();
        factory.speedDeliver();

    }
}

/**
 * 通用产品接口
 */
interface Transport{
    void deliver();
    void speedDeliver();
}

/**
 * 具体产品:Truck
 */
class Truck implements Transport{
    @Override
    public void deliver() {
        System.out.println("在盒子中以陆路运输。");
    }

    @Override
    public void speedDeliver() {
        System.out.println("卡车加速1倍运输。");
    }
}

/**
 * 具体产品:Ship
 */
class Ship implements Transport{
    @Override
    public void deliver() {
        System.out.println("在集装箱中以海路运输。");
    }
    @Override
    public void speedDeliver() {
        System.out.println("ship 无法加速。以原速度运输");
    }
}

/**
 * 通用创建者(工厂)
 */
abstract class Factory{
    public void deliver(){
        Transport product = createProduct();
        product.deliver();
    }

    public void speedDeliver(){
        Transport product = createProduct();
        product.speedDeliver();
    }
    protected abstract Transport createProduct();
}

/**
 * 具体创建者:Truck
 */
class TruckFactory extends Factory {

    @Override
    protected Transport createProduct() {
        return new Truck();
    }
}

/**
 * 具体创建者:Ship
 */
class ShipFactory extends Factory {

    @Override
    protected Transport createProduct() {
        return new Truck();
    }
}

简单工厂

简单工厂模式 描述了一个类, 它拥有一个包含大量条件语句的构建方法, 可根据方法的参数来选择对何种产品进行初始化并将其返回。 人们通常会将简单工厂与普通的工厂或其它创建型设计模式混淆。 在绝大多数情况下, 简单工厂是引入工厂方法抽象工厂模式时的一个中间步骤。 简单工厂通常没有子类。 但当从一个简单工厂中抽取出子类后, 它看上去就会更像经典的工厂方法模式了。 顺便提一句, 如果你将一个简单工厂声明为 abstract类型, 它并不会神奇地变成抽象工厂模式。

public class FactoryMethodTest {
    public static void main(String[] args) {
        new Application().getProduct("1").method1();
        /**
         * ProductA.method1 executed..
         */
    }
}
interface Product{
    void method1();
}
class ProductFactory{
    static Product getProduct(String type){
        if("1".equals(type)){
            return new ProductA();
        } else {
            return new ProductB();
        }
    }
}
class ProductA implements Product{
    @Override
    public void method1(){
        System.out.println("ProductA.method1 executed..");
    }
}
class ProductB implements Product{
    @Override
    public void method1(){
        System.out.println("ProductB.method1 executed..");
    }
}
class Application{
    Product createProduct(String type){
        return ProductFactory.getProduct(type);
    }
    Product getProduct(String type){
        Product product = createProduct(type);
        // 一系列操作共同的预处理操作。。。
        return product;
    }
}

抽象工厂模式(Abstract Factory Pattern)

问题背景

解决方案

抽象工厂模式代码实现

本文借助jdk中实现jdbc的原理来描述描述一下抽象工厂模式,首先定义两个抽象接口:连接接口和命令接口。

interface IConnect{
    void connect();
}
interface ICommand{
    void command();
}

此时再定义一个数据库操作util用来对数据库进行抽象对数据库进行处理。

interface IDatabaseUtils{
    IConnect getConnect();
    ICommand getCommand();
}

此时如果我们使用mysql作为数据库使用,那么具体实现一下数据库连接接口、数据库命令接口和mysql工具类。

class MysqlConnect implements IConnect{

    @Override
    public void connect() {
        System.out.println("connect mysql ...");
    }
}
class MysqlCommand implements ICommand{

    @Override
    public void command() {
        System.out.println("mysql command...");
    }
}

class MysqlUtils implements IDatabaseUtils{

    @Override
    public IConnect getConnect() {
        return new MysqlConnect();
    }

    @Override
    public ICommand getCommand() {
        return new MysqlCommand();
    }
}

假如封装到一个jar包中给所有人使用时,缺少oracle处理工具,我们只需要再具体实现一下数据库连接接口、数据库命令接口和oracle工具类,而不需要去动原有代码

class OracleConnect implements IConnect{

    @Override
    public void connect() {
        System.out.println("connect oracle ...");
    }
}
class OracleCommand implements ICommand{

    @Override
    public void command() {
        System.out.println("oracle command...");
    }
}

class OracleUtils implements IDatabaseUtils{

    @Override
    public IConnect getConnect() {
        return new OracleConnect();
    }

    @Override
    public ICommand getCommand() {
        return new OracleCommand();
    }
}

对于上面的示例代码,我们可以通过下面这种方式简单调用,通过IDatabaseUtils引用而不需要关注被调用的具体实现细节

public class AbstractFactoryTest {
    public static void main(String[] args) {
        IDatabaseUtils iDatabaseUtils = new OracleUtils();

        // 不再需要关注被调用的具体细节
        iDatabaseUtils.getConnect().connect();
        iDatabaseUtils.getCommand().command();
    }
}

总结:抽象工厂模式就是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。优点:1.可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理;2.当增加一个新的产品族时不需要修改原代码,满足开闭原则。

单例模式(Singleton Pattern)

建造者模式(Builder Pattern)

class Product{
    private String productName;
    private String part1;
    private String part2;
    public Product(String productName, String part1, String part2){
        this.productName = productName;
        this.part1 = part1;
        this.part2 = part2;

    }
    static class Builder{
        private String productName;
        private String part1;
        private String part2;
        public Builder productName(String productName) {
            this.productName = productName;
            return this;
        }

        public Builder part1(String part1) {
            this.part1 = part1;
            return this;
        }

        public Builder part2(String part2) {
            this.part2 = part2;
            return this;
        }
        public Product build(){
            return new Product(this.productName, this.part1, this.part2);
        }
    }

    @Override
    public String toString() {
        return "Product{" +
                "productName='" + productName + '\'' +
                ", part1='" + part1 + '\'' +
                ", part2='" + part2 + '\'' +
                '}';
    }
}

原型模式(Prototype Pattern)

/**
 * 模型定义:
 * 指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
 *
 * @date 2020/3/23 23:11
 */
public class ProtoTypeTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Product product = new Product("part1", "part2", "part3", "part4", new Part("xxx"));
        Product clone = product.clone();
        System.out.println(product);
        System.out.println(clone);
        System.out.println("---------------对部分数据进行修改----------------");
        clone.setPart1("part1A");
        clone.getPart().setName("YYY");
        System.out.println(product);
        System.out.println(clone);
    }
}
class Part implements Cloneable{
    String name;

    @Override
    protected Part clone() throws CloneNotSupportedException {
        return (Part) super.clone();
    }

    public Part(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Part{[" + hashCode() + "]"+
                "name='" + name + '\'' +
                '}';
    }

}
class Product implements Cloneable{
    String part1;
    String part2;
    String part3;
    String part4;

    public Part getPart() {
        return part;
    }

    public void setPart(Part part) {
        this.part = part;
    }

    Part part;
    // ...


    public Product(String part1, String part2, String part3, String part4,Part part) {
        this.part1 = part1;
        this.part2 = part2;
        this.part3 = part3;
        this.part4 = part4;
        this.part = part;
    }

    @Override
    protected Product clone() throws CloneNotSupportedException {
        // 进行深拷贝

        Product product = (Product) super.clone();
        product.setPart(product.getPart().clone());
        return product;
    }

    public String getPart1() {
        return part1;
    }

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public String getPart2() {
        return part2;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    public String getPart3() {
        return part3;
    }

    public void setPart3(String part3) {
        this.part3 = part3;
    }

    public String getPart4() {
        return part4;
    }

    public void setPart4(String part4) {
        this.part4 = part4;
    }

    @Override
    public String toString() {
        return "Product{[" + hashCode() + "]"+
                "part1='" + part1 + '\'' +
                ", part2='" + part2 + '\'' +
                ", part3='" + part3 + '\'' +
                ", part4='" + part4 + '\'' +
                ", part=" + part +
                '}';
    }
}

结构型模式

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

过滤器模式(Filter、Criteria Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

/**
 * 装饰者模式:扩展一个类的功能或给一个类附加职责
 *
 * 优点:
 * 在不改变原有对象的基础上给一个对象扩展功能
 * 使用不同的组合可以实现不同的效果
 * 符合开闭原则
 *
 *
 * @author lin.luo@hand-china.com
 * @date 2020/3/31 0:11
 */
public class DecoratorTest {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
//        component.operation();
        // 在原有的基础上添加功能
        component = new ConcreteDecorator1(component);
//        component.operation();
        component = new ConcreteDecorator2(component);
        component.operation();
    }
}
interface Component{
    void operation();
}
class ConcreteComponent implements Component{

    @Override
    public void operation() {
        System.out.println("拍照");
    }
}
abstract class Decorator implements Component{
    Component component;

    public Decorator(Component component) {
        this.component = component;
    }
}
class ConcreteDecorator1 extends Decorator{
    public ConcreteDecorator1(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        component.operation();
        System.out.println("美颜");
    }
}
class ConcreteDecorator2 extends Decorator{

    public ConcreteDecorator2(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        component.operation();
        System.out.println("滤镜");
    }
}

享元模式(Flyweight Pattern)

/**
 * 享元模式:运用共享技术有效地支持大量细粒度的对象
 * 借助全局变量完成对对象的共享
 * 对于大量相同的对象,可以节省系统内存
 *
 * @date 2020/3/30 23:58
 */
public class FlyWeightTest {
    public static void main(String[] args) {
        TreeNode treeNode1 = new TreeNode(3, 4, TreeFactory.getTree("A", "XXXX"));
        TreeNode treeNode2 = new TreeNode(3, 4, TreeFactory.getTree("A", "XXXX"));
        TreeNode treeNode3 = new TreeNode(3, 4, TreeFactory.getTree("B", "XXXX"));
    }

}
class TreeFactory{
    private static HashMap<String, Tree> map = new HashMap<>();
    public static Tree getTree(String name, String data){
        if(map.containsKey(name)){
            return map.get(name);
        }
        Tree tree = new Tree(name, data);
        map.put(name, tree);
        return tree;
    }
}
class TreeNode{
    private int x;
    private int y;
    private Tree tree;
    public TreeNode(int x, int y, Tree tree) {
        this.x = x;
        this.y = y;
        this.tree = tree;
    }
}
class Tree{
    private String name;
    private String data;

    public Tree(String name, String data) {
        this.name = name;
        this.data = data;
        System.out.println("create tree"+name);
    }

    public String getName() {
        return name;
    }

    public String getData() {
        return data;
    }
}

代理模式(Proxy Pattern)

门面模式(Facade Pattern)

public class FacadeTest {
    public static void main(String[] args) {
        new Facade().facadeDoSomething();
    }
}
class client{
}
class Facade{
    void facadeDoSomething(){
        new SubSystem1().method1();
        new SubSystem2().method2();
        new SubSystem3().method3();
    }
}

class SubSystem1{
    public void method1(){
        System.out.println("sub system1 method1");
    }
}
class SubSystem2{
    public void method2(){
        System.out.println("sub system2 method2");
    }
}
class SubSystem3{
    public void method3(){
        System.out.println("sub system3 method3");
    }
}

行为型模式

责任链模式(Chain of Responsibility Pattern)

class Request{
    private boolean loggedOn;
    private boolean frequentOk;
    private boolean isPermits;
    private boolean containsSensitiveWords;
    private String requestBody;

    public Request(boolean loggedOn, boolean frequentOk, boolean isPermits, boolean containsSensitiveWords, String requestBody) {
        this.loggedOn = loggedOn;
        this.frequentOk = frequentOk;
        this.isPermits = isPermits;
        this.containsSensitiveWords = containsSensitiveWords;
        this.requestBody = requestBody;
    }

    public boolean isLoggedOn() {
        return loggedOn;
    }

    public void setLoggedOn(boolean loggedOn) {
        this.loggedOn = loggedOn;
    }

    public boolean isFrequentOk() {
        return frequentOk;
    }

    public void setFrequentOk(boolean frequentOk) {
        this.frequentOk = frequentOk;
    }

    public boolean isPermits() {
        return isPermits;
    }

    public void setPermits(boolean permits) {
        isPermits = permits;
    }

    public boolean isContainsSensitiveWords() {
        return containsSensitiveWords;
    }

    public void setContainsSensitiveWords(boolean containsSensitiveWords) {
        this.containsSensitiveWords = containsSensitiveWords;
    }

    public String getRequestBody() {
        return requestBody;
    }

    public void setRequestBody(String requestBody) {
        this.requestBody = requestBody;
    }
}
abstract class Handler{
    Handler next;

    public Handler(Handler next) {
        this.next = next;
    }

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }
    abstract boolean process(Request request);
}
class FequentOkHandler extends Handler{

    public FequentOkHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.print("访问频率控制:");
        if(request.isFrequentOk()){
            System.out.println("ok");
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            } else {
                return true;
            }
        }
        System.out.println("error");
        return false;
    }
}

class IsPermitsHandler extends Handler{


    public IsPermitsHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.print("权限访问控制:");
        if(request.isPermits()){
            System.out.println("ok");
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            } else {
                return true;
            }

        }
        System.out.println("error");
        return false;
    }
}

class LoggedOnHandler extends Handler{

    public LoggedOnHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.print("登录权限控制:");
        if(request.isLoggedOn()){
            System.out.println("ok");
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            } else {
                return true;
            }

        }
        System.out.println("error");
        return false;
    }
}

class ContainsSensitiveWordsHandler extends Handler{

    public ContainsSensitiveWordsHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.print("敏感词权限控制:");
        if(request.isContainsSensitiveWords()){
            System.out.println("ok");
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            } else {
                return true;
            }
        }
        System.out.println("error");
        return false;
    }
}
public class ChainOfResponsibilityTest {
    public static void main(String[] args) {
        Request request = new Request(true, true, false, true, "hha");
        Handler handler = new FequentOkHandler(new LoggedOnHandler(new ContainsSensitiveWordsHandler(new IsPermitsHandler(null))));
        if(handler.process(request)){
            System.out.println("开始进行业务处理");
        }else {
            System.out.println("请求异常");
        }
    }
}

命令模式(Command Pattern)

解释器模式(Interpreter Pattern)

迭代器模式(Iterator Pattern)

迭代器模式是一种用于顺序访问集合对象的元素,但是不需要知道集合对象的底层表示的模式。主要目的是在不暴露聚合对象的内部结构的情况下,让外部代码透明地访问聚合的内部数据。

迭代器模式主要包含以下角色。

  1. 抽象聚合(Container)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
  2. 具体聚合(MyRepository)角色:实现抽象聚合类,返回一个具体迭代器的实例。
  3. 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。
  4. 具体迭代器(MyIterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

类图表示如下;

MyRepository.png
具体实现代码:

/**
 * 接口容器
 */
public interface Container {
    Iterator getIterator();
}
/**
 * 接口迭代器
 */
public interface Iterator {
    boolean hasNext();
    Object next();
}

/**
 * 具体容器
 */
public class MyRepository implements Container {
    public Object arr[] = {"a", "b", "c"};
    @Override
    public Iterator getIterator() {
        return new MyIterator();
    }

    /**
     * 具体迭代器
     */
    private class MyIterator implements Iterator{

        int index;

        @Override
        public boolean hasNext() {
            return index < arr.length;
        }

        @Override
        public Object next() {
            if(this.hasNext()){
                return arr[index++];
            }
            return null;
        }
    }
}

/**
 * 测试类
 */
public class IteratorTest {
    public static void main(String[] args) {
        Container container = new MyRepository();
        Iterator iterator = container.getIterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

中介者模式(Mediator Pattern)

备忘录模式(Memento Pattern)

观察者模式(Observer Pattern)

package com.lin.observe_pattern;  
  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
  
public class ObservePatternTest {  
    public static void main(String[] args) {  
        EventManager eventManager = new EventManager("A", "B");  
        eventManager.subscribe("A", new ListenerA());  
        eventManager.subscribe("A", new ListenerB());  
        eventManager.subscribe("B", new ListenerA());  
        eventManager.subscribe("B", new ListenerB());  
        eventManager.notify("B", "改变世界");  
    }  
}  
  
class EventManager{  
    Map<String, List<EventListener>> listeners = new HashMap<>();  
  
    public EventManager(String... operations) {  
        for (String operation : operations) {  
            this.listeners.put(operation, new ArrayList<>());  
        }  
    }  
  
    public void subscribe(String eventType, EventListener listener) {  
        List<EventListener> users = listeners.get(eventType);  
        users.add(listener);  
    }  
  
    public void unsubscribe(String eventType, EventListener listener) {  
        List<EventListener> users = listeners.get(eventType);  
        users.remove(listener);  
    }  
  
    public void notify(String eventType, String msg) {  
        List<EventListener> users = listeners.get(eventType);  
        for (EventListener listener : users) {  
            listener.comsumer(eventType, msg);  
        }  
    }  
  
}  
  
/**  
 * 通用观察者接口,定义comsumer方法,消费通知的消息  
 */  
interface EventListener{  
    void comsumer(String eventType, String msg);  
}  
  
class ListenerA implements EventListener{  
  
    @Override  
    public void comsumer(String eventType, String msg) {  
        System.out.println("ListenerA收到通知:"+eventType+"-"+msg+",准备xxx");  
    }  
}  
  
class ListenerB implements EventListener{  
  
    @Override  
    public void comsumer(String eventType, String msg) {  
        System.out.println("ListenerB收到通知:"+eventType+"-"+msg+",准备yyy");  
    }  
}

状态模式(State Pattern)

空对象模式(Null Object Pattern)

策略模式(Strategy Pattern)

public class StrategyTest {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.move();
        dog.setMoveable(new DogMove());
        dog.move();
    }
}

interface Moveable{
    void move();
}
interface Attackable{
    void attack();
}
class Runable implements Moveable{

    @Override
    public void move() {
        System.out.println("------ run -----");
    }
}

class DogMove implements Moveable{

    @Override
    public void move() {
        System.out.println("狗摇着尾巴移动");
    }
}

abstract class Animal{
    Moveable moveable;
    Attackable attackable;

    public Animal() {
    }

    public Animal(Moveable moveable, Attackable attackable) {
        this.moveable = moveable;
        this.attackable = attackable;
    }

    abstract public void display();
    abstract void move();
    abstract void attack();

    public Moveable getMoveable() {
        return moveable;
    }

    public void setMoveable(Moveable moveable) {
        this.moveable = moveable;
    }

    public Attackable getAttackable() {
        return attackable;
    }

    public void setAttackable(Attackable attackable) {
        this.attackable = attackable;
    }
}


class Dog extends Animal{
    public Dog() {
        super(new Runable(), null);
    }

    public Dog(Moveable moveable, Attackable attackable) {
        super(moveable, attackable);
    }

    @Override
    public void display() {
        System.out.println("------ 狗 ----------");
    }

    @Override
    void move() {
        moveable.move();
    }

    @Override
    void attack() {
        attackable.attack();
    }
}

模板模式(Template Pattern)

模板方法模式的目的就是在不改变现有类的算法结构下,将一些具体步骤延迟到子类中,

/**
 * 模式定义:
 * 定义一个操作的算法骨架,而将一些步骤延迟到子类中。
 * Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
 *
 * Servlet Api & Spring中的应用
 * javax.servlet.http.HttpServlet
 * org.springframework.web.servlet.mvc.AbstractController
 *
 * @author 2493468168@qq.com
 * @date 2020/3/22 14:55
 */
public class TemplateMethodTest {
    public static void main(String[] args) {
        AbstractClass abstractClass = new SubClass();
        abstractClass.operate();
        System.out.println("--------------");
        AbstractClass abstractClass2 = new SubClass2();
        abstractClass2.operate();
        /**
         * pre...
         * step1..
         * templateMethod1()
         * step final...
         * --------------
         * pre...
         * step1..
         * templateMethod2()
         * step final...
         */
    }
}
abstract class AbstractClass{
    public void operate(){
        System.out.println("pre...");
        System.out.println("step1..");
        templateMethod();
        System.out.println("step final...");
    }
    abstract void templateMethod();

}

class SubClass extends AbstractClass{

    @Override
    void templateMethod() {
        System.out.println("templateMethod1()");
    }
}
class SubClass2 extends AbstractClass{

    @Override
    void templateMethod() {
        System.out.println("templateMethod2()");
    }
}

访问者模式(Visitor Pattern)

参考资料: 设计模式目录:22种设计模式 (refactoringguru.cn)