精华内容
下载资源
问答
  • 常见问题的解决模式
    千次阅读
    2020-11-27 15:38:56

    RabbitMQ常见问题以及解决措施

    1. RabbitMQ消息丢失
      这个是RabbitMQ最常见的问题,RabbitMQ丢失分三种情况,生产者消息丢失,RabbitMQ消息丢失,消费者消息丢失.

      1. 生产者消息丢失
        生产者在发送消息给RabbitMQ,在中途有可能因为网络问题导致消息丢失,我们可以选择RabbitMQ提供的事务,也可以用confirm模式,就是生产者确认
        事务:
        channel.tsSelect开启事务;
        channel.txRollback出现问题事务回滚
        channel.txCommit成功后提交事务
        confirm模式:
        生产者发送消息,每个消息分配一个id,如果RabbitMQ接收到消息返回ack,如果没有收到放回nack,这个时候生产者只需要重新发送这个消息即可,可以结合这个机制在内存里设置消息id的状态,多长时间没有f返回ack就是失败,重新发送消息.
        事务和confirm对比:
        事务是属于同步的,在你提交一个事务会阻塞在那里,其他的消息是不能继续发送的,这样很容易影响性能,而confirm是异步的就是发送完我可以继续发送另一条消息,在正常使用中推荐使用confirm模式

      2. RabbitMQ消息丢失
        RabbitMQ数据丢失,可以用持久化分为两个步骤:
        首选创建queue的时候将其设置为持久化,这样可以保证RabbitMQ持久化queue的元数据,而不会持久化queue的数据,第二步将消息的deliveryMode设置为2,就是将消息设置为持久化,此时消息就会持久化到磁盘上,即使RabbitMQ重启,也会从磁盘上恢复queue,恢复queue里的数据
        跟生产者的confirm配合,如过持久化到磁盘上再返回ack,如果还没持久化就RabbitMQ挂掉了,生产者没有收到ack,还是会重新发送消息.

      3. 消费者消息丢失
        消费者有可能因为刚接到消息还没有处理就重启了,但是RabbitMQ以为他处理了,这样就会导致消息丢失,合理的解决方案是关闭自动ack,可以通过api来进行调用,等自己的代码处理完成之后,可以ack,这样即使你没有消费RabbitMQ也知道你是没有去消费的,这个时候RabbitMQ可以把消息交给其他的consumer进行消费,避免消息丢失

    2. 如何保证重复消费
      全局唯一ID+redis,首先生产者在发送消息时,为每条消息设置一个全局唯一的messageId,消费者拿到消息后,使用setnx命令,将messageId作为key放到redis中:setnx(messageId,1),若返回1,说明之前没有消费过,正常消费;若返回0,说明这条消息之前已消费过,抛弃。

    3. 如何保证顺序消费
      将一个queue拆分为了多个queue,这样一来,一个consumer对应一个queue,或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理

    更多相关内容
  • 集群模式Data ONTAP常见问题解答.pdf
  • 本系列的第3部分描述了针对最常见的、经常发生的大数据问题及其解决方案的原子模式和复合模式。本文将推荐可以用于架构大数据解决方案的三个解决方案模式。每个解决方案模式都使用了一个复合模式,该模式由逻辑组件...
  • 问题归类在各自的子主题下,以便专注于重复应用常见模式而不是随机解决问题。 所有问题都可以在上,其中一些要求 。 前言 强烈建议您阅读《第1、2、3、4、8和10章,以熟悉以下数据结构及其操作: 数组 地图 ...
  • 常见Android错误:精选的常见问题和错误消息列表以及解决方法。 该列表仍处于开发模式
  • Java常见设计模式总结

    万次阅读 多人点赞 2021-09-18 17:18:54
    项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。...

     一、设计模式总述:

    1、什么是设计模式:

            设计模式是一套经过反复使用的代码设计经验,目的是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 设计模式于己于人于系统都是多赢的,它使得代码编写真正工程化,它是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。总体来说,设计模式分为三大类:

    • 创建型模式:共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
    • 结构型模式:共7种:适配器模式、装饰器模式、代理模式、桥接模式、外观模式、组合模式、享元模式
    • 行为型模式:共11种:策略模式、模板方法模式、观察者模式、责任链模式、访问者模式、中介者模式、迭代器模式、命令模式、状态模式、备忘录模式、解释器模式

    其实还有两类:并发型模式和线程池模式,用一个图片来整体描述一下:

    2、设计模式的六大原则:

    (1)开闭原则 (Open Close Principle) :

            开闭原则指的是对扩展开放,对修改关闭。在对程序进行扩展的时候,不能去修改原有的代码,想要达到这样的效果,我们就需要使用接口或者抽象类

    (2)依赖倒转原则 (Dependence Inversion Principle):

            依赖倒置原则是开闭原则的基础,指的是针对接口编程,依赖于抽象而不依赖于具体

    (3)里氏替换原则 (Liskov Substitution Principle) :

            里氏替换原则是继承与复用的基石,只有当子类可以替换掉基类,且系统的功能不受影响时,基类才能被复用,而子类也能够在基础类上增加新的行为。所以里氏替换原则指的是任何基类可以出现的地方,子类一定可以出现。

            里氏替换原则是对 “开闭原则” 的补充,实现 “开闭原则” 的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。

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

            使用多个隔离的接口,比使用单个接口要好,降低接口之间的耦合度与依赖,方便升级和维护方便

    (5)迪米特原则 (Demeter Principle):

            迪米特原则,也叫最少知道原则,指的是一个类应当尽量减少与其他实体进行相互作用,使得系统功能模块相对独立,降低耦合关系。该原则的初衷是降低类的耦合,虽然可以避免与非直接的类通信,但是要通信,就必然会通过一个“中介”来发生关系,过分的使用迪米特原则,会产生大量的中介和传递类,导致系统复杂度变大,所以采用迪米特法则时要反复权衡,既要做到结构清晰,又要高内聚低耦合。

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

            尽量使用组合/聚合的方式,而不是使用继承。

    二、Java的23种设计模式:

            接下来我们详细介绍Java中23种设计模式的概念,应用场景等情况,并结合他们的特点及设计模式的原则进行分析

    1、创建型-工厂方法模式:

    工厂方法模式分为三种:

    (1)简单工厂模式:

    建立一个工厂类,并定义一个接口对实现了同一接口的产品类进行创建。首先看下关系图:

    (2)工厂方法模式:

    工厂方法模式是对简单工厂模式的改进,简单工厂的缺陷在于不符合“开闭原则”,每次添加新产品类就需要修改工厂类,不利于系统的扩展维护。而工厂方法将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。UML关系图如下:

     (3)静态工厂方法模式:

    静态工厂模式是将工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

    工厂方法模式详情文章:Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

    2、创建型-抽象工厂模式:

            抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

            但该模式的缺点在于添加新的行为时比较麻烦,如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。

            UML结构图如下:

    抽象工厂模式详情:Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

    3、创建型-建造者模式:

             建造者模式将复杂产品的创建步骤分解在在不同的方法中,使得创建过程更加清晰,从而更精确控制复杂对象的产生过程;通过隔离复杂对象的构建与使用,也就是将产品的创建与产品本身分离开来,使得同样的构建过程可以创建不同的对象;并且每个具体建造者都相互独立,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。UML结构图如下:

     建造者模式详情:Java设计模式之创建型:建造者模式

    4、创建型-单例模式:

            单例模式可以确保系统中某个类只有一个实例,该类自行实例化并向整个系统提供这个实例的公共访问点,除了该公共访问点,不能通过其他途径访问该实例。单例模式的优点在于:

    • 系统中只存在一个共用的实例对象,无需频繁创建和销毁对象,节约了系统资源,提高系统的性能
    • 可以严格控制客户怎么样以及何时访问单例对象。

    单例模式的写法有好几种,主要有三种:懒汉式单例、饿汉式单例、登记式单例。

    单例模式详情:Java设计模式之创建型:单例模式

    5、创建型-原型模式:

            原型模式也是用于对象的创建,通过将一个对象作为原型,对其进行复制克隆,产生一个与源对象类似的新对象。UML类图如下:

     在 Java 中,原型模式的核心是就是原型类 Prototype,Prototype 类需要具备以下两个条件:

    • 实现 Cloneable 接口:
    • 重写 Object 类中的 clone() 方法,用于返回对象的拷贝;

    Object 类中的 clone() 方法默认是浅拷贝,如果想要深拷贝对象,则需要在 clone() 方法中自定义自己的复制逻辑。

    • 浅复制:将一个对象复制后,基本数据类型的变量会重新创建,而引用类型指向的还是原对象所指向的内存地址。
    • 深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。

            使用原型模式进行创建对象不仅简化对象的创建步骤,还比 new 方式创建对象的性能要好的多,因为 Object 类的 clone() 方法是一个本地方法,直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显;

    原型模式详情:Java设计模式之创建型:原型模式

            

            上面我们介绍了5种创建型模式,下面我们就开始介绍下7种结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中对象的适配器模式是各种模式的起源,如下图:

    6、结构型-适配器模式:

            适配器模式主要用于将一个类或者接口转化成客户端希望的格式,使得原本不兼容的类可以在一起工作,将目标类和适配者类解耦;同时也符合“开闭原则”,可以在不修改原代码的基础上增加新的适配器类;将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性,但是缺点在于更换适配器的实现过程比较复杂。

            所以,适配器模式比较适合以下场景:

    • (1)系统需要使用现有的类,而这些类的接口不符合系统的接口。
    • (2)使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。

    下面有个非常形象的例子很好地说明了什么是适配器模式:

    适配器模式的主要实现有三种:类的适配器模式、对象的适配器模式、接口的适配器模式。三者的使用场景如下:

    • 类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
    • 对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
    • 接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。

    适配器模式详情:Java设计模式之结构型:适配器模式

    7、结构型-装饰器模式:

            装饰器模式可以动态给对象添加一些额外的职责从而实现功能的拓展,在运行时选择不同的装饰器,从而实现不同的行为;比使用继承更加灵活,通过对不同的装饰类进行排列组合,创造出很多不同行为,得到功能更为强大的对象;符合“开闭原则”,被装饰类与装饰类独立变化,用户可以根据需要增加新的装饰类和被装饰类,在使用时再对其进行组合,原有代码无须改变。装饰器模式的UML结构图如下:

            但是装饰器模式也存在缺点,首先会产生很多的小对象,增加了系统的复杂性,第二是排错比较困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

    装饰器模式详情:Java设计模式之结构型:装饰器模式

    8、结构型-代理模式:

            代理模式的设计动机是通过代理对象来访问真实对象,通过建立一个对象代理类,由代理对象控制原对象的引用,从而实现对真实对象的操作。在代理模式中,代理对象主要起到一个中介的作用,用于协调与连接调用者(即客户端)和被调用者(即目标对象),在一定程度上降低了系统的耦合度,同时也保护了目标对象。但缺点是在调用者与被调用者之间增加了代理对象,可能会造成请求的处理速度变慢。UML结构图如下:

    代理模式详情:Java设计模式之结构型:代理模式

    9、结构型-桥接模式:

            桥接模式将系统的抽象部分与实现部分分离解耦,使他们可以独立的变化。为了达到让抽象部分和实现部分独立变化的目的,桥接模式使用组合关系来代替继承关系,抽象部分拥有实现部分的接口对象,从而能够通过这个接口对象来调用具体实现部分的功能。也就是说,桥接模式中的桥接是一个单方向的关系,只能够抽象部分去使用实现部分的对象,而不能反过来。 

            桥接模式符合“开闭原则”,提高了系统的可拓展性,在两个变化维度中任意扩展一个维度,都不需要修改原来的系统;并且实现细节对客户不透明,可以隐藏实现细节。但是由于聚合关系建立在抽象层,要求开发者针对抽象进行编程,这增加系统的理解和设计难度。桥接模式的UML结构图如下:

            就像在Java中我们使用 JDBC 连接数据库时,在各个数据库之间进行切换,基本不需要动太多的代码,原因就是使用了桥接模式,JDBC 提供统一接口,每个数据库提供各自的实现,然后由桥接类创建一个连接数据库的驱动,使用某一个数据库的时候只需要切换一下就行。JDBC 的结构图如下:

             在 JDBC 中,桥接模式的实现化角色 (Implementor) 为的 Driver 接口,具体实现化 (Concrete Implementor) 角色对应 MysqlDriver、OracleDriver 和 MariadbDriver,扩展抽象化 (Refined Abstraction) 角色对应 DriverManager,不具有抽象化 (Abstraction) 角色作为扩展抽象化角色的父类。

    桥接模式详情:Java设计模式之结构型:桥接模式

    10、结构型-外观模式:

            外观模式通过对客户端提供一个统一的接口,用于访问子系统中的一群接口。使用外观模式有以下几点好处:

    (1)更加易用:使得子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟外观类交互就可以了;

    (2)松散耦合:将客户端与子系统解耦,让子系统内部的模块能更容易扩展和维护。

    (3)更好的划分访问层次:通过合理使用 Facade,可以更好地划分访问的层次,有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。

            但是如果外观模式对子系统类做太多的限制则减少了可变性和灵活性,所以外观模式适用于为复杂子系统提供一个简单接口,提高系统的易用性场景 以及 引入外观模式将子系统与客户端进行解耦,提高子系统的独立性和可移植性。

            外观模式的UML结构图如下:

    外观模式详情: Java设计模式之结构型:外观模式

    11、结构型-组合模式:

            组合模式将叶子对象和容器对象进行递归组合,形成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性,能够像处理叶子对象一样来处理组合对象,无需进行区分,从而使用户程序能够与复杂元素的内部结构进行解耦。

            组合模式最关键的地方是叶子对象和组合对象实现了相同的抽象构建类,它既可表示叶子对象,也可表示容器对象,客户仅仅需要针对这个抽象构建类进行编程,这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。组合模式的UML结构图如下:

    组合模式详情: Java设计模式之结构型:组合模式

    12、结构型-享元模式:

            享元模式通过共享技术有效地支持细粒度、状态变化小的对象复用,当系统中存在有多个相同的对象,那么只共享一份,不必每个都去实例化一个对象,极大地减少系统中对象的数量,从而节省资源。

            享元模式的核心是享元工厂类,享元工厂类维护了一个对象存储池,当客户端需要对象时,首先从享元池中获取,如果享元池中存在对象实例则直接返回,如果享元池中不存在,则创建一个新的享元对象实例返回给用户,并在享元池中保存该新增对象,这点有些单例的意思。

            工厂类通常会使用集合类型来保存对象,如 HashMap、Hashtable、Vector 等等,在 Java 中,数据库连接池、线程池等都是用享元模式的应用。

            享元模式的UML结构图如下:

             Java 中,String 类型就是使用享元模式,String 对象是 final 类型,对象一旦创建就不可改变。而 Java 的字符串常量都是存在字符串常量池中的,JVM 会确保一个字符串常量在常量池中只有一个拷贝。

            而且提到共享池,我们也很容易联想到 Java 里面的JDBC连接池,通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能!

    享元模式详情:Java设计模式之结构型:享元模式

            前面我们介绍了7种结构型设计模式,接下来我们介绍一下11种行为型设计模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。先来张图,看看这11中模式的关系:

     13、行为型-策略模式:

            将类中经常改变或者可能改变的部分提取为作为一个抽象策略接口类,然后在类中包含这个对象的实例,这样类实例在运行时就可以随意调用实现了这个接口的类的行为。

            比如定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换,使得算法可独立于使用它的客户而变化,这就是策略模式。UML结构图如下:

            策略模式的优点在于可以动态改变对象的行为;但缺点是会产生很多策略类,并且策略模式的决定权在用户,系统只是提供不同算法的实现,所以客户端必须知道所有的策略类,并自行决定使用哪一个策略类; 

            策略模式适用用于以下几种场景:

    • (1)应用程序需要实现特定的功能服务,而该程序有多种实现方式使用,所以需要动态地在几种算法中选择一种
    • (2)一个类定义了多种行为算法,并且这些行为在类的操作中以多个条件语句的形式出现,就可以将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

    策略模式详情:Java设计模式之行为型:策略模式

    14、行为型-模板方法:

            模板方法是基于继承实现的,在抽象父类中声明一个模板方法,并在模板方法中定义算法的执行步骤(即算法骨架)。在模板方法模式中,可以将子类共性的部分放在父类中实现,而特性的部分延迟到子类中实现,只需将特性部分在父类中声明成抽象方法即可,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤,不同的子类可以以不同的方式来实现这些逻辑。

            模板方法模式的优点在于符合“开闭原则”,也能够实现代码复用,将不变的行为转移到父类,去除子类中的重复代码。但是缺点是不同的实现都需要定义一个子类,导致类的个数的增加使得系统更加庞大,设计更加抽象。模板方法模式的UML图如下:

    模板方法详情:Java设计模式之行为型:模板方法模式

    15、行为型-责任链模式:

            职责链可以将请求的处理者组织成一条链,并将请求沿着链传递,如果某个处理者能够处理请求则处理,否则将该请求交由上级处理。客户端只需将请求发送到职责链上,无须关注请求的处理细节,通过职责链将请求的发送者和处理者解耦了,这也是职责链的设计动机。        

           职责链模式可以简化对象间的相互连接,因为客户端和处理者都没有对方明确的信息,同时处理者也不知道职责链中的结构,处理者只需保存一个指向后续者的引用,而不需要保存所有候选者的引用。

            另外职责链模式增加了系统的灵活性,我们可以任意增加或更改处理者,甚至更改处理者的顺序,不过有可能会导致一个请求无论如何也得不到处理,因为它可能被放置在链末端。

    所以责任链模式有以下几个优点:

    • (1)降低耦合度,将请求的发送者和接收者解耦。反映在代码上就是不需要在类中写很多丑陋的 if….else 语句,如果用了职责链,相当于我们面对一个黑箱,只需将请求递交给其中一个处理者,然后让黑箱内部去负责传递就可以了。
    • (2)简化了对象,使得对象不需要链的结构。
    • (3)增加系统的灵活性,通过改变链内的成员或者调动他们的次序,允许动态地新增或者删除处理者
    • (4)增加新的请求处理类很方便。

    但是责任链模式也存在一些缺点:

    • (1)不能保证请求一定被成功处理
    • (2)系统性能将受到一定影响,并且可能会造成循环调用。
    • (3)可能不容易观察运行时的特征,而且在进行代码调试时不太方便,有碍于除错。

            责任链模式的UML结构图如下:

    责任链模式详情:Java设计模式之行为型:责任链模式

    16、行为型-观察者模式:

            观察者模式又称为 发布-订阅模式,定义了对象之间一对多依赖关系,当目标对象(被观察者)的状态发生改变时,它的所有依赖者(观察者)都会收到通知。一个观察目标可以对应多个观察者,而这些观察者之间没有相互联系,所以能够根据需要增加和删除观察者,使得系统更易于扩展,符合开闭原则;并且观察者模式让目标对象和观察者松耦合,虽然彼此不清楚对方的细节,但依然可以交互,目标对象只知道一个具体的观察者列表,但并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。

            但观察者模式的缺点在于如果存在很多个被观察者的话,那么将需要花费一定时间通知所有的观察者,如果观察者与被观察者之间存在循环依赖的话,那么可能导致系统崩溃,并且观察者模式没有相应的机制让观察者知道被观察对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。观察者模式的UML结构图如下:

     观察者模式详情:Java设计模式之行为型:观察者模式

    17、行为型-访问者模式:

            访问者模式就是一种分离对象数据结构与行为 (基于数据结构的操作) 的方法,通过这种分离,达到为一个被访问者动态添加新的操作而无需做其它修改的效果,使得添加作用于这些数据结构的新操作变得简单,并且不需要改变各数据结构,为不同类型的数据结构提供多种访问操作方式,这样是访问者模式的设计动机。

            除了使新增访问操作变得更加简单,也能够在不修改现有类的层次结构下,定义该类层次结构的操作,并将有关元素对象的访问行为集中到一个访问者对象中,而不是分散搞一个个的元素类中。

           但访问者模式的缺点在于让增加新的元素类变得困难,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,违背了“开闭原则”的要求;

            所以访问者模式适用于对象结构中很少改变,但经常需要在此对象结构上定义新的操作的系统,使得算法操作的增加变得简单;或者需要对一个对象结构中进行很多不同并且不相关的操作,并且需要避免让这些操作污染这些对象,也不希望在增加新操作时修改这些类的场景。

            访问者模式的UML结构图如下:

            从上面的 UML 结构图中我们可以看出,访问者模式主要分为两个层次结构,一个是访问者层次结构,提供了抽象访问者和具体访问者,主要用于声明一些操作;一个是元素层次结构,提供了抽象元素和具体元素,主要用于声明 accept 操作;而对象结构 ObjectStructure 作为两者的桥梁,存储了不同类型的对象,以便不同的访问者来访问,相同访问者可以以不同的方式访问不同的元素,所以在访问者模式中增加新的访问者无需修改现有代码,可扩展行强。

            在访问者模式使用了双分派技术,所谓双分派技术就是在选择方法的时候,不仅仅要根据消息接收者的运行时区别,还要根据参数的运行时区别。在访问者模式中,客户端将具体状态当做参数传递给具体访问者,这里完成第一次分派,然后具体访问者作为参数的“具体状态”中的方法,同时也将自己this作为参数传递进去,这里就完成了第二次分派。双分派意味着得到的执行操作决定于请求的种类和接受者的类型。

     访问者模式详情:Java设计模式之行为型:访问者模式

    18、行为型-中介者模式:

             中介者模式通过中介者对象来封装一系列的对象交互,将对象间复杂的关系网状结构变成结构简单的以中介者为核心的星形结构,对象间一对多的关联转变为一对一的关联,简化对象间的关系,便于理解;各个对象之间的关系被解耦,每个对象不再和它关联的对象直接发生相互作用,而是通过中介者对象来与关联的对象进行通讯,使得对象可以相对独立地使用,提高了对象的可复用和系统的可扩展性。

            在中介者模式中,中介者类处于核心地位,它封装了系统中所有对象类之间的关系,除了简化对象间的关系,还可以对对象间的交互进行进一步的控制。中介者模式的UML结构图如下:

            但是,中介者对象封装了对象之间的关联关系,导致中介者对象变得比较庞大复杂,所承担的责任也比较多,维护起来也比较困难,它需要知道每个对象和他们之间的交互细节,如果它出问题,将会导致整个系统都会出问题。

    中介者模式详情:Java设计模式之行为型:中介者模式

    19、行为型-命令模式:

            命令模式的本质是将请求封装成对象,将发出命令与执行命令的责任分开,命令的发送者和接收者完全解耦,发送者只需知道如何发送命令,不需要关心命令是如何实现的,甚至是否执行成功都不需要理会。命令模式的关键在于引入了抽象命令接口,发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。

            使用命令模式的优势在于降低了系统的耦合度,而且新命令可以很方便添加到系统中,也容易设计一个组合命令。但缺点在于会导致某些系统有过多的具体命令类,因为针对每一个命令都需要设计一个具体命令类。

            命令模式的UML结构图如下:

    命令模式详情: Java设计模式之行为型:命令模式

    20、行为型-状态模式:

            状态模式,就是允许对象在内部状态发生改变时改变它的行为,对象看起来就好像修改了它的类,也就是说以状态为原子来改变它的行为,而不是通过行为来改变状态。

            当对象的行为取决于它的属性时,我们称这些属性为状态,那该对象就称为状态对象。对于状态对象而言,它的行为依赖于它的状态,比如要预订房间,只有当该房间空闲时才能预订,想入住该房间也只有当你预订了该房间或者该房间为空闲时。对于这样的一个对象,当它的外部事件产生互动的时候,其内部状态就会发生变化,从而使得他的行为也随之发生变化。

            状态模式的UML结构图如下:

     从上面的UML结构图我们可以看出状态模式的优点在于:

    (1)封装了转换规则,允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块

    (2)将所有与状态有关的行为放到一个类中,可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 

    但是状态模式的缺点在于:

    (1)需要在枚举状态之前需要确定状态种类

    (2)会导致增加系统类和对象的个数。

    (3)对 “开闭原则” 的支持并不友好,新增状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

    所以状态模式适用于:代码中包含大量与对象状态有关的条件语句,以及对象的行为依赖于它的状态,并且可以根据它的状态改变而改变它的相关行为。

    状态模式详情:Java设计模式之行为型:状态模式

    21、行为型-备忘录模式:

            备忘录模式提供了一种恢复状态的机制,在不破坏封装的前提下,捕获对象的某个时刻内部状态,并保存在该对象之外,保证该对象能够恢复到某个历史状态;备忘录模式将保存的细节封装在备忘录中,除了创建它的创建者之外其他对象都不能访问它,并且实现了即使要改变保存的细节也不影响客户端。但是备忘录模式都是多状态和多备份的,会早用较多的内存,消耗资源。备忘录模式的额UML结构图如下:

             备忘录模式的核心就是备忘录 Memento,在备忘录中存储的就是原发器 Originator 的部分或者所有的状态信息,而这些状态信息是不能够被其他对象所访问的,也就是说我们是不能使用备忘录之外的对象来存储这些状态信息,如果暴漏了内部状态信息就违反了封装的原则,故备忘录除了原发器外其他对象都不可以访问。所以为了实现备忘录模式的封装,我们需要对备忘录的访问做些控制:

    (1)对原发器:可以访问备忘录里的所有信息。

    (2)对负责人 caretaker:不可以访问备忘录里面的数据,但是他可以保存备忘录并且可以将备忘录传递给其他对象。

    (3)其他对象:不可访问也不可以保存,它只负责接收从负责人那里传递过来的备忘录同时恢复原发器的状态。

    备忘录模式详情:Java设计模式之行为型:备忘录模式

    22、行为型-迭代器模式:

            迭代器模式提供一种访问集合中的各个元素,而不暴露其内部表示的方法。将在元素之间游走的职责交给迭代器,而不是集合对象,从而简化集合容器的实现,让集合容器专注于在它所应该专注的事情上,更加符合单一职责原则,避免在集合容器的抽象接口层中充斥着各种不同的遍历操作。迭代器模式的UML结构图如下:

    迭代器模式详情:Java设计模式之行为型:迭代器模式

    23、行为型-解释器模式:

            解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例。

            解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中,它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。    

            解释器模式中除了能够使用文法规则来定义一个语言,还能通过使用抽象语法树来更加直观表示、更好地地表示一个语言的构成,每一颗抽象语法树对应一个语言实例。抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。

            解释器模式的UML如下:

     解释器模式详情:Java设计模式之行为型:解释器模式


    相关推荐阅读:

    Spring常见面试题总结

    SpringMVC常见面试题总结

    Mybatis常见面试题总结

    MySQL常见面试题总结

    Redis常见面试题总结

    RabbitMQ消息队列常见面试题总结

    ElasticSearch搜索引擎常见面试题总结

    计算机网络常见面试题总结

    操作系统常见面试题总结

    Java基础、集合、多线程常见面试题总结

    Java虚拟机常见面试题总结

    Java常见设计模式总结

    海量数据处理的方法总结


    参考文章:

    Java之美[从菜鸟到高手演变]之设计模式

    Java之美[从菜鸟到高手演变]之设计模式二

    Java之美[从菜鸟到高手演变]之设计模式三

    Java之美[从菜鸟到高手演变]之设计模式四

    展开全文
  • 这些反模式涵盖了六种常见的流程建模场景。本文的第1部分将重点介绍与控制流建模有关的两种场景。我们将讨论当您需要在业务流程模型中描述分支和迭代行为时出现的反模式。对于归纳为反模式的典型错误,我们将引入...
  • 常见设计模式的解析和实现 常见设计模式的解析和实现(C+ + )之一-Factory 模式 作用 定义一个用于创建对象的接口让子类决定实例化哪一个类Factory Method 使一 个类的实例化延迟到其子类 UML 结构图 抽象基类 1) ...
  • 在上篇文章给大家介绍了javascript面向对象基础,本...因此为了解决这个问题,人们开始使用以下几种方式来常见对象。 工厂模式模式抽象了创建对象的具体过程,用函数来以特定接口创建对象的细节 function cPerson
  • vim的使用方法和常见问题解决方法 vim的使用方法和常见问题解决方法 vim的使用方法和常见问题解决方法 vim的使用方法和常见问题解决方法 vim的使用方法和常见问题解决方法
  • B2C 类型电子商务网站常见盈利模式分析 B2C 电子商务的经营模式决定了 B2C 电子商务企业的盈利模式 不同类型的 B2C 电子商务企业其盈利模式是不同的一般来说 B2C 电子商务企业主要是通过以下几个方面获得盈利 1销售...
  • C++ 常见设计模式

    千次阅读 2022-04-25 17:21:25
    一、定义:定义一系列算法(将算法定义为虚函数,子类重写它),将它们...三、解决什么问题:在运行时根据需要透明地更改对象的算法;将算法与对象本身解耦。 原始代码设计(伪代码): enum TaxBase { CN_Tax, ...

    面向对象设计原则

    1、依赖倒置原则:上层模块和实现细节都应该依赖于抽象。eg)上层模块为获取国家的税率,实现细节会包括中国税率、美国税率等,不能直接在上层模块里利用if/else编码实现具体细节,而应该抽象出一个基类(内含税率计算函数),各实现细节模块继承这个抽象基类,根据虚函数动态绑定的特点利用基类指针或引用来解耦合。

    2、开放封闭原则:类模块应该是可扩展的,但是不能修改。eg)如果还有日本的税率需要计算,不能直接在上层模块编码实现,而是重写一个子类继承抽象基类用来计算。

    3、单一职责原则:每一个类都应该专注于做一件事,这样可以降低类的复杂度。

    4、优先使用对象组合而不是类继承:继承在某种程度上破坏了类的封装性,可让另一个类成为本类的成员。类A中包含类B的指针而不是类B对象,比较灵活。

    什么是设计模式以及好处优点

    一·、定义·:设计模式其实上就是用来让代码写的更加规范,方便后期维护扩展,提高软件的复用性、灵活性、扩展性。

    二、优点:

    ***设计模式的使用将提高软件系统的开发效率和软件质量,节省开发成本

    ***设计模式有助于初学者深入理解面向对象思想

    ***设计模式使设计方案更加灵活,方便后期维护修改

    策略模式

    一、定义:定义一系列算法(将算法定义为虚函数,子类重写它),将它们封装起来,并使他们可互相替换(变化)。

    二、应用场景:在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担(例如if/else条件判断语句有很多判断语句不会被执行)。

    三、解决什么问题:在运行时根据需要透明地更改对象的算法;将算法与对象本身解耦。

    原始代码设计(伪代码)

    enum TaxBase {
        CN_Tax,
        US_Tax,
        DE_Tax,
        FR_Tax       //更改
    };
    
    class SalesOrder{
        TaxBase tax;
    public:
        double CalculateTax(){
            //...
            
            if (tax == CN_Tax){
                //CN***********
            }
            else if (tax == US_Tax){
                //US***********
            }
            else if (tax == DE_Tax){
                //DE***********
            }
            else if (tax == FR_Tax){  //更改
                //...
            }
    
            //....
         }
        
    };

    加入策略设计模式之后的代码(伪代码):

    class TaxStrategy{   // 父类
    public:
        virtual double Calculate(const Context& context)=0;  // 父类纯虚函数
        virtual ~TaxStrategy(){}
    };
    
    
    class CNTax : public TaxStrategy{
    public:
        virtual double Calculate(const Context& context){  //子类重写父类虚函数
            //***********
        }
    };
    
    class USTax : public TaxStrategy{
    public:
        virtual double Calculate(const Context& context){
            //***********
        }
    };
    
    class DETax : public TaxStrategy{
    public:
        virtual double Calculate(const Context& context){
            //***********
        }
    };
    
    //扩展
    //*********************************
    class FRTax : public TaxStrategy{
    public:
        virtual double Calculate(const Context& context){
            //.........
        }
    };
    
    
    class SalesOrder{
    private:
        TaxStrategy* strategy; //父类指针指向子类对象 发生多态
    
    public:
        SalesOrder(StrategyFactory* strategyFactory){
            this->strategy = strategyFactory->NewStrategy();
        }
        ~SalesOrder(){
            delete this->strategy;
        }
    
        public double CalculateTax(){
            //...
            CNTax context();
            
            double val = strategy->Calculate(context); //多态调用
            //...
        }
        
    };
    

    总结:使用继承,将算法通过纯虚函数向子类中进行传递,每个子类都可以单独进行实现,在使用算法时便可以准确调用对应的函数,不需要包含不需要使用到的算法。在使用对if/else条件判断语句进行替换的时候,策略模式可能是一个不错的选择。

    观察者模式

    一·、定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的观察者对象都得到通知并自动更新。

    二、主要构成:

    抽象被观察者:将所有观察者对象保存到一个集合里,并提供增加、删除观察者对象的接口

    具体被观察者:有关状态存入具体观察者对象,具体被观察者的内部状态发生改变时,给所有登记过的观察者发通知。负责实现抽象被观察者中的方法。

    抽象观察者:为具体观察者提供一个更新接口,该接口声明了更新数据的方法。

    具体观察者:实现抽象观察者定义的更新接口,以便更新自身状态

    三、举例:我的微信公众是被观察者,微信用户是观察者,有多个微信用户关注了我的公众号,当我的公众号更新订阅时就会通知这些订阅了的微信用户。

    四、具体应用场景:消息更新、广播机制、消息传递(发布-订阅模式)

    单例模式

    单例模式只允许类创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。分为懒汉模式和饿汉模式。

    一、多线程不安全版本

    优点:实现了一个类只有一个类对象,当再次进入函数创建时由于age不为空,直接return了。

    缺点:在多线程情况下会创建多个对象。如果线程a和线程b同时进入63行的函数,每个线程都会创建一个类对象,违反了单例模式原则。

    二、多线程安全版本  加锁

     优点:对函数全局加锁。线程a进入函数后获得锁,线程b不能再进入函数只能等待a释放锁。当线程a创建好age后结束函数并释放锁,这时b取得锁,发现age不为空,直接return了。保证了一个类只有一个类对象。

    缺点:加锁代价过高。如果后续的多线程全执行读操作,这会造成浪费,因为读不用加锁。后续多线程会等待锁释放,效率降低,尤其针对于高并发的网络服务器来说效率大大降低。

    三、双检查锁版本

    优点:解决了全执行读操作的多线程浪费且效率低下问题。只有age为空时才加锁。当线程a进入函数,会获得锁,给age赋值。后续执行读操作的多进程进入函数后发现age不为空,直接return了,方便了执行读操作的多线程。

    PS:为啥判断两次?

            ***线程a线程b同时在65 66行进入,如果不加第二次判断,第二个线程等待第一个线程释放锁后还是会创建多个类对象。

    缺点:68行代码 age=new Person()会由于内存读写reorder不安全导致双检查锁失效。理想情况下这行代码会分三步进行:1、分配内存;2、调用Person构造函数初始化内存;3、将new的内存地址返回后赋值给person。但是编译器有可能实际情况下会先分配内存然后直接将内存地址赋值给person,最后调用构造函数。这样的话person不为空了,第二个线程进入函数发现person不为空,直接return person了,但person是不能被使用的,因为内存没初始化。

    四、volatile 或者 atomic库   解决双检查锁版本的reorder问题

    1、volatile Person* age; //让编译器不reorder

    2、atomic<Person*> Person::age; //让编译器不reorder

    上述都是单例模式的懒汉模式:当外界第一次调用get_person()接口时才进行类的实例化。会出现多线程不安全问题

    因此有饿汉模式:类加载时就对类实例化。不会出现多线程不安全问题,不用加锁。C++11 保证静态局部变量的初始化过程是线程安全的。这里的线程安全指的是:一个线程在初始化 m 的时候,其他线程执行到 m 的初始化这一行的时候,就会挂起阻塞。

    工厂模式

    简单工厂模式:多了工厂基类

    class Splitter { //抽象基类
    public:
    	virtual void split() = 0;
    };
    class ImageSplitter : public Splitter{
    	virtual void split() {}//具体子类 重写基类虚函数
    };
    class VideoSplitter : public Splitter {
    	virtual void split() {}//具体子类 重写基类虚函数
    };
    
    class SplitterFactory {//工厂基类 充当第三方角色 不需要向工厂方法一样再创建具体工厂子类
    public:
    	Splitter* createSplitter(){
            if(...) return new ImageSplitter();//一般需要switch或if进行类型选择
            else if(...) return new VideoSplitter();//
        }
    };
    
    int main() {//常规做法
    	Splitter * splitter = new ImageSplitter();//常规做法 利用new创建具体细节对象
    	Splitter * splitter = new VideoSplitter();//上层模块还是依赖了具体细节 违背依赖倒置原则
    }
    
    
    int main() {//简单工厂模式 
    	SplitterFactory*  factory;
    	Splitter* splitter=factory->createSplitter();
        splitter.split();
    }

    工厂方法模式:绕开new,解决利用new创建对象时出现的紧耦合问题。多了工厂基类和具体工厂子类

    class Splitter { //抽象基类
    public:
    	virtual void split() = 0;
    };
    class ImageSplitter : public Splitter{
    	virtual void split() {}//具体子类 重写基类虚函数
    };
    class VideoSplitter : public Splitter {
    	virtual void split() {}//具体子类 重写基类虚函数
    };
    
    
    class SplitterFactory {//工厂基类
    public:
    	virtual Splitter* createSplitter() = 0;//纯虚函数 动态绑定
    };
    class ImageSplitterFactory : public SplitterFactory {//具体工厂
    public:
    	virtual Splitter* createSplitter() {
    		return new ImageSplitter();//将常规的new搬到了具体工厂子类中
    	}
    };
    class VideoSplitterFactory : public SplitterFactory {//具体工厂
    public:
    	virtual Splitter* createSplitter() {
    		return new VideoSplitter();//将常规的new搬到了具体工厂子类中
    	}
    };
    
    int main() {//常规做法 
    	Splitter * splitter = new ImageSplitter();//利用new创建具体细节对象
    	Splitter * splitter = new VideoSplitter();//这样的话上层模块还是依赖了具体细节 违背依赖倒置原则
    }
    
    int main() { //工厂方法模式
    	SplitterFactory*  factory;
    	Splitter* splitter = factory->createSplitter();//多态new。移出具体细节,让别人new去
    	splitter->split();
    }
    
    
    

    抽象工厂模式:对工厂方法进行优化

           假设上述imagesplitter和videospiltter除了有公共的split外,还有公共的merge和destroy等,那么需要再来一个merge基类工厂和destroy基类工厂以及对应的具体工厂子类。这样实现比较复杂且代码可读性不好,可将split、merge、destroy放进同一个抽象工厂里,此抽象工厂内含纯虚函数split、merge、destroy。能这样做的前提是split、merge、destroy这三者互相有联系。

    展开全文
  • 揭露 PHP 应用程序中出现的五个常见数据库问题 —— 包括数据库模式设计、数据库访问和使用数据库的业务逻辑代码 —— 以及它们的解决方案。
  • 本文主要对以太网在测试中出现的常见4种问题进行了分析及解答。
  • 本文将介绍最常见的和经常发生的大数据问题以及它们的解决方案。原子模式描述了使用、处理、访问和存储大数据的典型方法。复合模式由原子模式组成,并根据大数据解决方案的范围进行分类。由于每个复合模式都有若干个...
  • 广电EPON+EOC模式三网融合网络的常见故障与解决办法收集.pdf
  • 常见的23种设计模式的实例和名称,问题解决方案的描述,用java语言描述
  • 摄像头调试常见问题解决方法 希望对大家有用
  • Java中有哪几种常见的设计模式

    千次阅读 2020-03-27 14:31:30
    Java中一般认为有23种设计模式,分别是: 1.创建型模式,五种:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式; 2.结构性模式,七种: ...

    Java中一般认为有23种设计模式,分别是:

    1.创建型模式,五种:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式;

    2.结构型模式,七种:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。

    3.行为型模式,十一种:策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。

    常见的有:单例模式,工厂方法模式,抽象工厂模式,建造者模式,适配器模式,装饰模式,策略模式,代理模式。

    1.通过静态内部类来实现单例模式有什么好处?

    1.避免线程排队,阻塞,节约时间。

    2.调用getInstance()的时候,才会将符号引用变成直接引用,也就是初始化,类似懒加载,节约空间。

    2.静态代理和动态代理有什么区别,在安卓中的使用场景是?

    1.代理模式:分为静态代理和动态代理。例如:明星和经纪人就是一对被代理人和代理人。要明星表演就要通过经纪人来传达。我们把通过代理对象来间接操作目标对象的方式,称之为“代理模式”。

    好处:在实现目标对象的功能的基础上,可以扩展额外功能,而不用改动目标对象。

    静态代理:代理对象和目标对象要一起实现相同的接口,或者继承同一个父类。

    动态代理:在程序运行时生成代理对象。

    区别:

    在给多个方法相同的类进行代理的时候,静态代理需要实现多个接口,太过麻烦。这个时候使用动态代理比较好。动态代理不需要去实现接口。

    静态代理:代理对象在程序运行前就存在,要实现接口。

    动态代理:代理对象在程序运行中生成,不需要实现接口。

    场景:

    静态:四大组件跟AIDL和AMS进行跨进程通信。

    动态:Retrofit(基于OKHttp封装的网络请求框架)使用了动态代理,极大的提升了框架的扩展性和可维护性。

    具体:https://www.cnblogs.com/jie-y/p/10732347.html

    3.简单工厂、工厂方法、抽象工厂的区别?

    简单工厂:一个工厂方法可以创建不同类型的对象;

    工厂方法:一个具体工厂类只创建一个具体对象;

    抽象工厂:一个具体工厂类只创建一系列相关的对象。

    具体:https://www.cnblogs.com/heliusKing/p/11577837.html

    4.建造者模式

    将复杂对象创建的过程抽象出来,根据具体实现抽象的不同,生成的对象也不同。

    具体:https://www.jianshu.com/p/afe090b2e19c

    5.代理模式和装饰器模式的区别?

    1.定义:

    装饰器模式:给一个对象动态的添加一些额外功能,就增加功能来说,装饰器模式比生成子类更加灵活。

    2.区别:

    装饰器模式更加强调给一个对象添加功能,而代理模式更加强调对被代理对象的方法调用。装饰器模式是以客户端透明的方式为对象扩展功能的,而代理模式往往会隐藏被代理对象,在内部不想暴露出来。

    参考文章:https://www.cnblogs.com/adamjwh/p/9036358.html

    6.什么是桥接模式?

    桥接模式:主要为了应对某个类族有多个变化维度,导致子类类型急剧增加的场景。通过桥接模式把多个变化维度分隔开,使它们可以独立的变化,最后通过组合以应对多维变化,减少子类类型的数量和复杂度。

    具体:https://www.cnblogs.com/WindSun/p/10260547.html

    7.外观模式和中介模式的区别?

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

    具体:https://www.cnblogs.com/adamjwh/p/9048594.html

    中介模式:用来解决多个对象显式相互调用造成的耦合,使用一个中介来使耦合松散,使类之间减少依赖。

    具体:https://www.jianshu.com/p/298ef103b484

    区别:

    外观模式重点是对外封装统一的高层接口,便于用户使用;而中介模式是为了避免多个相互协作的对象直接引用,通过一个中介对象进行交互,使耦合松散,能够易于应对变化。

    8.策略模式和状态模式的区别?

    策略模式:定义了一组算法,把每个算法都封装起来,并且使他们可以互相切换。

    具体:https://www.cnblogs.com/adamjwh/p/11011095.html

    状态模式:当一个对象内部状态改变时,允许改变其行为,这个对象看起来好像改变了其类。

    具体:https://www.jianshu.com/p/5bf844141687

    区别:

    虽然他们类型结构一致,但是本质是不一样的。策略模式重点是切换整个算法,而状态模式是改变状态,改变其行为。

    9.适配器模式,代理模式,装饰器模式,外观模式的异同?

    适配器模式:将一个已经存在的接口转换成客户希望的另一个接口,使接口不兼容的类可以协同工作。

    具体:https://blog.csdn.net/wwwdc1012/article/details/82780560

    同:

    它们都是作为中间层,起到用户间接调用真实类方法的作用。

    异:

    1.使用场景和思想不一样;

    2.代理模式,代理目标对象,控制对该对象的访问;

    外观模式,外观对象提供子系统各元件功能简化为共同层次的调用接口,它主要起“简化作用”;

    适配器模式,是对其他对象接口的一种转换行为,将原接口转换为目标接口,达到适配的效果;

    装饰器模式,给对象动态增加功能。

    代理是“控制访问行为”,外观是“简化行为”,适配器是“转换行为”,装饰器是“新增行为”。

     

     

    参考文章:https://juejin.im/post/5e5c5c52f265da575f4e7558

     

     

     

     

     

     

     

    展开全文
  • 普通模式有4个基本要素:模式名称(pattern name)、问题(problem)、解决方案(solution)、效果(consequences)。部分常见的Java设计模式有以下10种:1、抽象工厂模式(Abstract Factory):提供一个创建一系列相关或相互...
  • iOS常见的设计模式:工厂设计模式

    千次阅读 2022-03-14 16:34:10
    iOS常见的设计模式:工厂设计模式 简单工厂模式: 简单工厂模式(Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有...
  • 备注 11 Internet Explorer 11 桌面应用程序将于 2022 年 6 月 ... 现在使用的 IE11 应用和网站可以在 Microsoft Edge 的 Internet Explorer 模式下打开。 若要了解更多信息,请参阅 Internet Exploreron Windows ...
  • 下面跟大家介绍一个鲜为人知的功能【SW安全模式】,该功能适用于一些常见的SW问题排查。我们先来认识一个工具,SOLIDWORKS RX!这个工具非常有用,但是很多SOLIDWORKS的使用者很可能都没听说过这个工具。 我们从...
  • 大数据技术之-03-Hadoop学习-Hadoop运行模式常见错误及解决方案.docx
  • Java 常见的面试题(设计模式

    千次阅读 2021-05-12 16:22:24
    Java 常见的面试题(设计模式
  • ### 解决方法在全局的router-view组件上设置一个key值,此key值为一个时间戳或者随机字符,对于keep-alive的组件不做这个处理。### 问题二:``` router.go(0)```这种写法本质上是想达到刷新当前页面的目的,但是在...
  • Java企业级常见的设计模式

    万次阅读 2020-08-06 09:02:28
    抽象工厂模式:工厂的创建由子类决定,其子类的子类实现业务。(也称为超级工厂模式) 单例模式:系统中保持一个实例,实例方法私有,公开全局访问方法。 [懒汉式]: 获取实例对象时再实例化。加锁的实例化线程安全...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 658,985
精华内容 263,594
关键字:

常见问题的解决模式