设计模式知识点总结-DX的笔记

设计模式的分类

  • 设计模式分为三大类23三种,用于代码中的设计出现,用于解决代码安全问题
    请添加图片描述

七大原则

  • 开闭原则(总原则)
    • 开放/封闭原则:Open Closed Principle
    • 软件的实体应用应该对扩展开放,但对修改关闭,开闭原则同样也是面向对象的设计核心,这个原则可以将面向对象的技术称之为可维护,可扩展,可复用,灵活性可完全体现出来
    • 设计人员必须对他设计的模块应该对哪些变化封闭,哪些变化需要开发者做出判断,并且设计时需要先预测出最大可能性,并且将开放性的抽取出来,实现热拔插效果
  • 单一职责原则
    • SRP:Single responsibility principle
    • 不要存在多于一个导致类变更的原因,代表每一个类应该实现单一原则如果不是则需要拆分
    • 单一原则代表的是:比如饭店中如果有一个人做菜,洗菜,上菜,买菜;如果出现这种情况就必须拆分原因是他做的事情太多太杂;所以需要让功能切分,例如厨师炒菜,服务员上菜等等进行功能的划分
  • 里氏代换原则
    • LSP:Liskov Substitution Principle
    • 面向对象设计的基本原则之一,任何基类可以出现的地方,那么其子类也可以出现,用于继承(带有父子关系)复用的基石,只有当衍生类可以替换掉基类时,软件单位的功能不受任何影响(子类的功能已经全部完成以及对基类(父类)的补充也全部完成)可以用子类替换掉基类(父类),里氏代换原则是对开闭原则的补充,里氏代换原则说白了就是对实现抽象话的步骤进行规范
    • 基类是程序中的最基础的类:例如Java中的Object类就是Java中的基类
    • 子类可以实现基类的方法以及扩展基类的方法,当所有的功能都是子类完成时就可以替换基类,以及在完成基类的方法后也可以扩展功能,但是不能修改基类的功能(删除,增加,修改)
  • 依赖倒置原则
    • Dependence Inversion Principle
    • 依赖倒置原则是使用开闭原则的基础,高层模块不应该依赖于底层模块,两个都应该依赖于抽象方法,并且抽象方法不能依赖于细节(不能有实现的细节),细节应该依赖于抽象,主要针对接口编程,不要针对于实现编程
    • 主要针对接口编程代表接口中不要带有具体实现的细节,而是交由子类实现细节,这个是完全面向对象设计标志,编写时主要考虑的是如何对抽象编程(接口编程)而不是对细节编程
    • 面向接口编程说白了就是隐藏细节让子类实现细节
  • 接口隔离原则
    • Interface Segregation Principle
    • 每个接口不能存在子类用不到的方法但却又必须实现的方法,如果一旦存在则须要将其隔离(写到其他须要用到的接口之中)单独创建
    • 例如:厨师接口应该有的方法:炒菜,但是不应该有的是切菜洗菜摘菜等方法,所以这些方法就应该抽离出去单独建立
  • 迪米特法则(最少知道原则)
    • Law of Demeter
    • 迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。英文简写为: LOD。
    • 比如:厨师和修车的(他们是没有任何关系的),但是修车的又需要吃饭,吃饭就需要跟厨师沟通,此时需要使用第三者转发(通知),例如:服务员或者外卖员
  • 合成/聚合复用原则
    • 尽量使用合成/聚合,尽量不要使用继承
    • 聚合:表示一个弱的拥有关系,体现是A对象可以包含B对象,但是B对象不是A对象的一部分(在B对象中创建A对象并且调用方法,但不能直接继承)
    • 合成:表示一种强的拥有关系,体现是严格的部分和整体的关系,体现出部分与整体生命周期一致(他们两个是共消亡的)

创建型模式

工厂模式

  • 工厂模式的作用就是用于创建对象
  • 工厂模式分为三种
    1. 简单工厂模式
    2. 方法工厂模式
    3. 静态工厂模式
简单工厂模式
  • 实现发送消息发送邮件功能(两个功能)
  1. 创建发送接口
/**
 * 发送接口,有一个发送的抽象方法
 */
public interface Sender {
    void send();
}
  1. 创建两个实现类(一个邮件的,一个消息的)
public class MailSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送邮件...");
    }
}
public class MessageSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送信息...");
    }
}
  1. 创建工厂类,用于创建发送消息或邮件的对象
/**
 * 工厂-->用于生产发送信息和发送邮件类(创建他们的对象并返回)
 */
public class SenderFactory {
    public Sender builder(String sendType) {
        if ("mail".equals(sendType)) {
            return new MailSender();
        }
        if ("message".equals(sendType)) {
            return new MessageSender();
        }
        return null;
    }
}
  1. 测试类
public class TestFactory {
    public static void main(String[] args) {
        // 1. 创建工厂对象
        SenderFactory senderFactory = new SenderFactory();
        // 通过工厂对象创建我们需要用到的发送的方式
        Sender mail = senderFactory.builder("mail");
        Sender message = senderFactory.builder("message");
        // 创建完毕后使用方法
        mail.send();
        message.send();
        // 调用不存在的方法
        Sender weChat = senderFactory.builder("WeChat");
        weChat.send();
    }
}

简单工厂类虽然简单但是容易出现问题例如我们输入一个不存在的发送方式就会出现空指针异常

方法工厂模式

工厂方法模式出现的原因是简单工厂方法模式在创建对象时容易出现问题,一旦出现则报错,而工厂方法模式不需要判断方式则不易出错
将原本简单工厂中的判断改为方法直接调用创建

  1. 创建发送接口
public interface Sender {
    void send();
}
  1. 创建两个实现类(一个邮件的,一个消息的)
public class MailSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送邮件...");
    }
}
public class MessageSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送信息...");
    }
}
  1. 创建工厂类,用于创建发送消息或邮件的对象
/**
 * 工厂-->用于生产发送信息和发送邮件类(创建他们的对象并返回)
 */
public class SenderFactory {
    // 返回mail发送邮件对象
    public Sender builderMail() {
        return new MailSender();
    }
    // 返回message发送信息对象
    public Sender builderMessage() {
        return new MessageSender();
    }
}
  1. 测试类
public class TestFactory {
    public static void main(String[] args) {
        // 1. 创建工厂对象
        SenderFactory senderFactory = new SenderFactory();
        // 2. 通过工厂方法创建对象
        Sender mail = senderFactory.builderMail();
        Sender message = senderFactory.builderMessage();
        // 3. 调用各自的方法
        mail.send();
        message.send();
        // 使用不存在就无法创建
        // senderFactory.weChat();
    }
}

工厂方法模式也是有弊端的,必须先创建工厂方法对象才能调用创建发送消息对象的方法

静态方法工厂模式

用于解决工厂方法模式出现的弊端,将原有的方法改为静态方法可以在不创建对象的情况下调用方法

  1. 创建发送接口
public interface Sender {
    void send();
}
  1. 创建两个实现类(一个邮件的,一个消息的)
public class MailSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送邮件...");
    }
}
public class MessageSender implements Sender {
    @Override
    public void send() {
        System.out.println("发送信息...");
    }
}
  1. 创建工厂类,用于创建发送消息或邮件的对象
/**
 * 工厂-->用于生产发送信息和发送邮件类(创建他们的对象并返回)
 */
public class SenderFactory {
    public static Sender builderMail() {
        // 返回mail发送邮件对象
        return new MailSender();
    }
    public static Sender builderMessage() {
        // 返回message发送信息对象
        return new MessageSender();
    }
}
  1. 测试类
public class TestFactory {
    public static void main(String[] args) {
        // 1. 通过工厂方法创建对象
        Sender mail = SenderFactory.builderMail();
        Sender message = SenderFactory.builderMessage();
        // 2. 调用各自的方法
        mail.send();
        message.send();
        // 使用不存在就无法创建
        // senderFactory.weChat();
    }
}

单例模式(面试会用到)

  • 用于创建对象
  • 能够确保在一个项目中使用的对象不会改变,并且每次使用的都是同一个
  • 能够确保程序中的内存不会因为频繁创建对象而变的紧张
  • 不会因为创建对象而产生过的垃圾对象,也不易出现内存溢出的问题
饿汉式

不管是否会用到此对象他都会先创建,先备好用的时候直接拿
不管调用多少次对象始终都只是创建同一个对象

  1. 饿汉式的创建方式
/**
 * 静态方法在不创建对象时就可以调用,但是静态方法是不是就会生成静态区
 */
public class Person {
    private String name;
    private Integer age;
    
    // 静态属性用于创建对象(用于饿汉式创建对象)
    // 由于静态的变量是共享型所以不管调用多少次,静态变量始终都是一个并且不会改变
    private static Person person = new Person();
    
    //单例模式要始终保持创建对象的唯一性,所以将构造方法设为私有的private
    private Person() {
    }
    
    public static Person newInstance() {
        return person;
    }

    public static void func01() {
        System.out.println("你好,我是饿汉式!");
    }
    //get....  set....
}

饿汉式缺点,如果我调用是其他的静态方法哪怕不需要获取当前类对象他也会创建,同样会造成静态内存当中出现垃圾对象

懒汉式

懒汉式就是懒,什么时候需要使用对象什么是创建,例如一个人什么时候饿了什么时候做饭或点外卖

  1. 懒汉式创建方式
public class Person {
    private String name;
    private Integer age;

    // 静态属性用于创建对象(用于懒汉式创建对象)
    // 由于静态的变量是共享型所以不管调用多少次,静态变量始终都是一个并且不会改变
    private static Person person = null;// = new Person();

    public static Person newInstance() {
        // 判断对象是否为null
        if (person == null) {
            person = new Person();
        }
        return person;
    }

    //保持创建对象的唯一性以,所以不应存有构造方法,所以将其设为私有的private
    private Person() {
    }

    public static void func01() {
        System.out.println("你好,我是懒汉式!");
    }
    //get....  set....
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        // 使用懒汉式创建对象
        Person.func01();
        // 调用newInstance
        Person person1 = Person.newInstance();
        Person person2 = Person.newInstance();
        Person person3 = Person.newInstance();
        Person person4 = Person.newInstance();
        // 输出Person内存地址
        System.out.println(person1);
        System.out.println(person2);
        System.out.println(person3);
        System.out.println(person4);
    }
}

懒汉式看着是解决了饿汉式的问题,但是如果在多线程情况下有可能会出现创建多次将上一次的对象覆盖

双重线程检测式

由于上面的懒汉式或饿汉式会出现多创建对象或者不管是否需要都会创建对象的问题,当前需要使用线程安全的方式升级懒汉式

  1. 双重线程检测式创建方式
public class Person {
    private String name;
    private Integer age;

    private static Person person = null;

    //使用静态同步方法非常非常影响性
    //在这里会多线程阻塞
    /*public synchronized static Person newInstance() {
        if (person == null) {
            person = new Person();
        }
        return person;
    }*/

    //使用同步代码块解决静态同步方法的问题
    public static Person newInstance() {
        if (person == null) {
            // 使用同步代码块创建对象
            //在这里会多线程阻塞
            synchronized (Person.class) {
                // 第二重检测对象是否为null
                if (person == null) {
                    person = new Person();
                }
            }
        }
        return person;
    }

    private Person() {
    }

    public static void func01() {
        System.out.println("你好,我是双重线程检测式!");
    }
    //get....  set....
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        // 使用循环+线程创建1000次Person对象
        for (int i = 0; i < 1000; i++) {
            // 线程创建对象
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 创建对象
                    Person person = Person.newInstance();
                    System.out.println(person);
                }
            }).start();
        }
    }
}

使用双重线程检测式已经算是比较完美的了,不会出现问题,但是不符合完全面向对象方式(未将实现完全封装)

嵌套内部类式

嵌套内部类式是双重线程检查式的升级版,作用是隐藏静态方法中的具体实现,而将具体实现使用内部类封装,将具体实现隐藏封装重新调用

  1. 嵌套内部类式
public class Person {
    private String name;
    private Integer age;

    // 使用内部类创建对象,此位置的静态属性就不需要了
    // private static Person person = null;
    
    private Person() {
    }
    
    public static Person newInstance() {
        return BuilderPerson.newInstance();
    }

    //创建静态私有内部类
    private static class BuilderPerson {
        
        private static Person person;

        // 将构造方法改为私有的
        private BuilderPerson() {
        }
        
        //创建对象
        private static Person newInstance() {
            if (person == null) {
                synchronized (Person.class) {
                    if (person == null) {
                        person = new Person();
                    }
                }
            }
            return person;
        }
    }

    public static void func01() {
        System.out.println("你好,我是嵌套内部类式!");
    }
    //get....  set....
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
                // 使用循环+线程创建1000次Person对象
                for (int i = 0; i < 1000; i++) {
                    // 线程创建对象
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            // 创建对象
                            Person person = Person.newInstance();
                            System.out.println(person);
                        }
                    }).start();
        }
    }
}

使用内部类式解决了双重线程检测式的问题,将所有的实现细节隐藏后重新调用

建造者模式

  • 用于构造对象,并且使用集合进行封装(创建一堆)
  • 每次创建时创建一堆不同的对象,从集合中取对象时,该对象将被移出集合(防止重复)
  1. Person类
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
// get... set...
}
  1. 建造者类
/**
 * 此类用于创建Person对象使用,并且使用集合装载创建的Person对象
 */
public class BuilderPerson {
    
    private List<Person> persons = new ArrayList<>();

    //无参构造方法,默认创建10个Person对象
    public BuilderPerson() {
        this(10);
    }

    //用于创建Person对象并添加到集合
    public BuilderPerson(int newCount) {
        if (newCount <= 0) {
            newCount = 10;
        }
        for (int i = 0; i < newCount; i++) {
            // 创建对象并添加到集合中
            persons.add(new Person());
        }
    }

    //用于获取集合中的Person对象
    public Person getPerson() {
        
        if (persons.isEmpty()) {
            // 如果集合中没有数据了返回null或则返回new Person()对象
            return new Person();
        }
        // 获取后删除当前集合中的元素
        int size = persons.size();
        Person person = persons.get(size - 1);
        persons.remove(size - 1);
        return person;
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        
        BuilderPerson builderPerson = new BuilderPerson();
        // 获取多个对象
        for (int i = 0; i < 20; i++) {
            Person person = builderPerson.getPerson();
            System.out.println(person.getAge());
        }
    }
}

结构型模式

结构性模式不创建对象,而是对代码的设计,通过设计能够更加面向对象编程(都是使用接口式)

适配器模式

1. 类的适配器模式

适配器模式案例:有一个接口,接口中有func01和func02两个方法,一旦有类继承了此接口就必须重写这两个方法
但是如果现在分别有两个类,A类和B类,两个类中分别有func01和func02的方法(分别定义的是func01和func02)
A类实现了接口中的一个方法,如果B类实现了接口且继承了A类,则B类只需实现另一个方法即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6YdWZtM1-1657760782490)(./img/42.png)]

  1. 接口
public interface InterfaceClass {
    void func01();
    void func02();
}
  1. A类
public class ClassA {
    public void func01() {
        System.out.println("Class A func01...");
    }
}
  1. B类
public class ClassB extends ClassA implements InterfaceClass {
    public void func02() {
        System.out.println("Class B func02...");
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) throws NoSuchMethodException {
        ClassB classB = new ClassB();
        classB.func01();
        classB.func02();
    }
}
2. 对象的适配器模式
  1. 创建接口
public interface InterfaceClass {
    void func01();
    void func02();
}
  1. ClassA
public class ClassA {
    public void func01() {
        System.out.println("Class A func01...");
    }
}
  1. ClassB
/**
 * 如果ClassB需要继承其他的对象就无法继承ClassA
 */
public class ClassB implements InterfaceClass {

    // 此时需要创建ClassA的对象(变量)
    private ClassA classA;
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    // 将InterfaceClass中的func01方法重写
    @Override
    public void func01() {
        //可以直接使用A对象的方法
        classA.func01();
    }

    public void func02() {
        System.out.println("Class B func02...");
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) throws NoSuchMethodException {
        ClassB classB = new ClassB(new ClassA());
        classB.func01();
        classB.func02();
    }
}
3. 接口的适配器模式

接口适配器模式主要以抽象类媒介在中间起作用
其实就是把接口变成抽象类,就不用重写全部方法了

  1. 接口
public interface InterfaceClass {
    void func01();
    void func02();
}
  1. 抽象类
public abstract class AbstractClass implements InterfaceClass {
    //重写两个方法但是不写逻辑代码
    @Override
    public void func01() {
    }
    @Override
    public void func02() {
    }
}
  1. 实现类A
public class ClassA extends AbstractClass {
    @Override
    public void func01() {
        System.out.println("Class A func01...");
    }
}
  1. 实现类B
public class ClassB extends AbstractClass {
    @Override
    public void func02() {
        System.out.println("Class B func02...");
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        ClassA classA = new ClassA();
        classA.func01();
        classA.func02();
        ClassB classB = new ClassB();
        classB.func01();
        classB.func02();
    }
}

装饰器模式

1. 装饰器模式概述

装饰器模式用于功能扩展(增加/删除)
例如相亲:小明的相亲流程–>穿上衣–>穿裤子–>穿鞋
也有可能小明买的廉价香水到了–>–>穿上衣–>穿裤子–>穿鞋–>喷香水
个人总结:解耦合,多模块(功能),顺序随意使用

2. 装饰器模式定义
  1. 接口
public interface BlindDateInterface {
    // 相亲方法
    void blindDateMethod();
}
  1. 实现类–>主类
/**
 * 装饰器之实现类穿裤子-->主类(相亲时必须做的事情)
 */
public class ChuanKuZi implements BlindDateInterface {
    @Override
    public void blindDateMethod() {
        System.out.println("穿裤子...");
    }
}
  1. 装饰器类有n个
/**
 * 装饰器之实现类穿上衣
 */
public class ChuanShangYi implements BlindDateInterface {
    // 使用泛型,创建相亲对象(想创建谁随心情)
    private BlindDateInterface blindDateInterface;

    // 构造方法创建相亲接口
    public ChuanShangYi(BlindDateInterface blindDateInterface) {
        this.blindDateInterface = blindDateInterface;
    }

    @Override
    public void blindDateMethod() {
        // 先调用其他的方法
        blindDateInterface.blindDateMethod();
        // 调用后再做自己的事情
        System.out.println("穿上衣...");
    }
}
 /**
 * 装饰器之实现类穿鞋子
 */
public class ChuanXieZi implements BlindDateInterface {
    
    private BlindDateInterface blindDateInterface;

    public ChuanXieZi(BlindDateInterface blindDateInterface) {
        this.blindDateInterface = blindDateInterface;
    }

    @Override
    public void blindDateMethod() {
        blindDateInterface.blindDateMethod();
        System.out.println("穿鞋子...");
    }
}
/**
 * 装饰器之实现类喷香水
 */
public class PenXiangShui implements BlindDateInterface {
    private BlindDateInterface blindDateInterface;
    public PenXiangShui(BlindDateInterface blindDateInterface) {
        this.blindDateInterface = blindDateInterface;
    }
    @Override
    public void blindDateMethod() {
        blindDateInterface.blindDateMethod();
        System.out.println("喷香水...");
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        // 相亲时第一个步骤就是穿裤子
        // 创建对象时按照顺序来
        ChuanKuZi ckz = new ChuanKuZi();
        // 穿上衣,并且传入功能
        ChuanShangYi csy = new ChuanShangYi(ckz);
        // 穿鞋子,并且传入功能
        ChuanXieZi cxz = new ChuanXieZi(csy);
        // // 喷香水,并且传入功能
        // PenXiangShui pxs = new PenXiangShui(cxz);
        // // 走你相亲去
        // pxs.blindDateMethod();
        cxz.blindDateMethod();
    }
}

装饰器模式的目的就是为了功能的扩展(增加或删除功能),可扩展维护(高解耦)

代理模式

1. 代理模式概述

例如张三打官司–>请律师(法外狂徒张三)–>打官司的人是张三需要要法外狂徒张三代理打官司–>这种就是程序中的代理模式

2. 代理模式定义
  1. 接口
public interface LitigateInterface {
    // 打官司方法
    void litigateFunc();
}
  1. 被代理对象
/**
 * 张三打官司-->为自己辩护
 */
public class ZhangSan implements LitigateInterface {
    @Override
    public void litigateFunc() {
        System.out.println("执行打官司方法...");
    }
}
  1. 代理对象
/**
 * 代理律师-->法外狂徒张三
 */
public class ProxyAttorney implements LitigateInterface {

    // 需要创建被代理对象-->我需要给谁打官司我得知道-->所以需要创建被代理对象
    private ZhangSan zhangSan;
    public ProxyAttorney() {
        this.zhangSan = new ZhangSan();
    }

    @Override
    public void litigateFunc() {
        // 调用被代理对象前调用方法
        before();
        // 代理律师询问张三情况-->需要调用张三的辩护方法
        zhangSan.litigateFunc();
        // 调用被代理对象后调用方法
        after();
    }

    /**
     * 代理对象中一般最少会有2个方法,在调用被代理对象方法前和在调用被代理对象方法后
     */
    private void before() {
        System.out.println("Proxy before..");
    }

    private void after() {
        System.out.println("Proxy after..");
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        // 创建代理对象
        ProxyAttorney proxyAttorney = new ProxyAttorney();
        // 打官司
        proxyAttorney.litigateFunc();
    }
}

代理模式其实就是在原有的基础上做增强(代码增强),也就是在我们使用某些类的中的方法时做些方法增强或者方法验证

行为型模式

1. 观察者模式

1. 观察者模式概述

观察者模式是一对多的模式(既一个类对应多个类,观察变化)
观察者模式也可被称之为(发布-订阅模式)
例如:京东购买商品时商品目前无货,那我们可以订阅等待有货后通知我们购买

2. 观察者模式定义
实现方式一
  1. 定义观察者接口
/**
 * 订阅者-->被通知者
 */
public interface SubscriberInterface {
    //更新方法-->用于接收发布者发布的消息而做响应的动作
    void update();
}
  1. 定义发布者接口
/**
 * 发布者-->用于发布信息给订阅者
 */
public interface ObserverInterface {
    // 添加观察者
    void addSubscriber(SubscriberInterface subscriber);
    // 删除观察者
    void deleteSubscriber(SubscriberInterface subscriber);
    // 通知观察者
    void noticeSubscriber();
}
  1. 定义订阅者实现类
/**
 * 订阅者实现类
 */
public class SubscriberImpl implements SubscriberInterface {

    // 添加商品属性,用于接收当前到货通知是什么货
    private String commodity;
    public SubscriberImpl(String commodity) {
        this.commodity = commodity;
    }

    @Override
    public void update() {
        System.out.println("当前您订阅的商品<" + commodity + ">到货了,您可以尽情的购买了!");
    }
}
  1. 定义发布者实现类
/**
 * 发布者实现类
 */
public class ObserverImpl implements ObserverInterface {

    // 订阅者集合(需要被观察的人有多少)(需要被通知的人有多少)
    private List<SubscriberInterface> subscribers;
    public ObserverImpl() {
        // 初始化订阅者集合
        subscribers = new ArrayList<>();
    }

    //添加订阅者
    @Override
    public void addSubscriber(SubscriberInterface subscriber) {
        subscribers.add(subscriber);
    }

    //删除订阅者
    @Override
    public void deleteSubscriber(SubscriberInterface subscriber) {
        subscribers.remove(subscriber);
    }

    //通知订阅者到货
    @Override
    public void noticeSubscriber() {
        // 通知所有的订阅者
        for (SubscriberInterface subscriber : subscribers) {
            // 调用订阅者的update方法即可
            subscriber.update();
        }
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        // 创建订阅者
        SubscriberInterface subscriber = new SubscriberImpl("充气床垫");
        // 创建发布者
        ObserverInterface observer = new ObserverImpl();
        // 添加订阅者
        observer.addSubscriber(subscriber);
        observer.addSubscriber(new SubscriberImpl("充气枕头"));
        observer.addSubscriber(new SubscriberImpl("充气鞋垫"));
        observer.addSubscriber(new SubscriberImpl("充气游泳圈"));
        observer.addSubscriber(new SubscriberImpl("充气气球"));
        // 通知到货
        observer.noticeSubscriber();
    }
}
实现方式二
  1. 定义观察者接口
/**
 * 订阅者-->被通知者
 */
public interface SubscriberInterface {
    void update(String commodity);
}
  1. 定义发布者接口
/**
 * 发布者-->用于发布信息给订阅者
 */
public interface ObserverInterface {
    // 添加观察者
    void addSubscriber(SubscriberInterface subscriber);
    // 删除观察者
    void deleteSubscriber(SubscriberInterface subscriber);
    // 通知观察者
    void noticeSubscriber();
}
  1. 定义订阅者实现类
/**
 * 订阅者实现类
 */
public class SubscriberImpl implements SubscriberInterface {
    
    private String name;
    public SubscriberImpl(String name) {
        this.name = name;
    }

    @Override
    public void update(String commodity) {
        System.out.println("尊敬的<" + name + ">当前您订阅的商品<" + commodity + ">到货了,您可以尽情的购买了!");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SubscriberImpl that = (SubscriberImpl) o;
        return Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}
  1. 定义发布者实现类
/**
 * 发布者实现类
 */
public class ObserverImpl implements ObserverInterface {

    // 使用发布者通知到货的商品
    private String commodity;
    // 订阅者集合(需要被观察的人有多少)(需要被通知的人有多少)
    private List<SubscriberInterface> subscribers;
    //空参构造方法用于创建Subscriber集合对象
    public ObserverImpl(String commodity) {
        this.commodity = commodity;
        // 初始化订阅者集合
        subscribers = new ArrayList<>();
    }

    //添加订阅者
    @Override
    public void addSubscriber(SubscriberInterface subscriber) {
        subscribers.add(subscriber);
    }

    //删除订阅者
    @Override
    public void deleteSubscriber(SubscriberInterface subscriber) {
        subscribers.remove(subscriber);
    }

    //通知订阅者到货
    @Override
    public void noticeSubscriber() {
        for (SubscriberInterface subscriber : subscribers) {
            subscriber.update(commodity);
        }
    }
}
  1. 测试类
public class Demo {
    public static void main(String[] args) {
        // 创建订阅者
        SubscriberInterface subscriber = new SubscriberImpl("小明");
        // 创建发布者
        ObserverInterface observer = new ObserverImpl("充气床垫");
        // 添加订阅者
        observer.addSubscriber(subscriber);
        observer.addSubscriber(new SubscriberImpl("小红"));
        observer.addSubscriber(new SubscriberImpl("小白"));
        observer.addSubscriber(new SubscriberImpl("小青"));
        observer.addSubscriber(new SubscriberImpl("小蓝"));
        // 通知到货
        observer.noticeSubscriber();
        System.out.println("==================================================");
        // 删除订阅者
        observer.deleteSubscriber(new SubscriberImpl("小明"));
        // 通知到货
        observer.noticeSubscriber();
    }
}

以上观察者模式(订阅/发布)将原本的角色互换原本订阅者应该频繁询问的状态更改为发布者直接发布通知

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值