精华内容
下载资源
问答
  • java 设计模式
    千次阅读
    2022-02-28 18:29:10

    Java面试题及答案(2022版),每道都是认真筛选出的高频面试题,助力大家能找到满意的工作!

    Java设计模式面试题及答案

    下载链接全部面试题及答案PDF

    1.请列举出在 JDK 中几个常用的设计模式?

    单例模式(Singleton pattern)用于 Runtime,Calendar 和其他的一些类中。工厂模式
    (Factory pattern)被用于各种不可变的类如 Boolean,像 Boolean.valueOf,观察者模式
    (Observer pattern)被用于 Swing 和很多的事件监听中。装饰器设计模式(Decorator
    design pattern)被用于多个 Java IO 类中。

    2.什么是设计模式?你是否在你的代码里面使用过任何设计模式?

    设计模式是世界上各种各样程序员用来解决特定设计问题的尝试和测试的方法。设计模式是代码可用性的延伸

    3.Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

    单例模式重点在于在整个系统上共享一些创建时较耗资源的对象。整个应用中只维护一个特定类实例,它被所有组件共同使用。Java.lang.Runtime 是单例模式的经典例子。从 Java5 开始你可以使用枚举(enum)来实现线程安全的单例。

    4.在 Java 中,什么叫观察者设计模式(observer design pattern)?

    观察者模式是基于对象的状态变化和观察者的通讯,以便他们作出相应的操作。简单的例子就是一个天气系统,当天气变化时必须在展示给公众的视图中进行反映。这个视图对象是一个主体,而不同的视图是观察者。

    5.使用工厂模式最主要的好处是什么?在哪里使用?

    工厂模式的最大好处是增加了创建对象时的封装层次。如果你使用工厂来创建对象,之后你可以使用更高级和更高性能的实现来替换原始的产品实现或类,这不需要在调用层做任何修改。

    6.举一个用 Java 实现的装饰模式(decorator design pattern)?它是作用于对象层次还是类层次?

    装饰模式增加强了单个对象的能力。Java IO 到处都使用了装饰模式,典型例子就是Buffered 系列类如 BufferedReader 和 BufferedWriter,它们增强了 Reader 和 Writer 对象,以实现提升性能的 Buffer 层次的读取和写入。

    7.在 Java 中,为什么不允许从静态方法中访问非静态变量?

    Java 中不能从静态上下文访问非静态数据只是因为非静态变量是跟具体的对象实例关联的,而静态的却没有和任何实例关联。

    8.设计一个 ATM 机,请说出你的设计思路?

    比如设计金融系统来说,必须知道它们应该在任何情况下都能够正常工作。不管是断电还是其他情况,ATM 应该保持正确的状态(事务) , 想想 加锁(locking)、事务(transaction)、错误条件(error condition)、边界条件(boundary condition) 等等。尽管你不能想到具体的设计,但如果你可以指出非功能性需求,提出一些问题,想到关于边界条件,这些都会是很好的。

    9.在 Java 中,什么时候用重载,什么时候用重写?

    如果你看到一个类的不同实现有着不同的方式来做同一件事,那么就应该用重写(overriding),而重载(overloading)是用不同的输入做同一件事。在 Java 中,重载的方法签名不同,而重写并不是。

    10.举例说明什么情况下会更倾向于使用抽象类而不是接口?

    接口和抽象类都遵循”面向接口而不是实现编码”设计原则,它可以增加代码的灵活性,可以适应不断变化的需求。下面有几个点可以帮助你回答这个问题:在 Java 中,你只能继承一个类,但可以实现多个接口。所以一旦你继承了一个类,你就失去了继承其他类的机会了。

    接口通常被用来表示附属描述或行为如:Runnable、Clonable、Serializable 等等,因此当你
    使用抽象类来表示行为时,你的类就不能同时是 Runnable 和 Clonable(注:这里的意思是指如果把 Runnable 等实现为抽象类的情况),因为在 Java 中你不能继承两个类,但当你使用接口时,你的类就可以同时拥有多个不同的行为。

    在一些对时间要求比较高的应用中,倾向于使用抽象类,它会比接

    口稍快一点。如果希望把一系列行为都规范在类继承层次内,并且可以更好地在同一个地方进行编码,那么抽象类是一个更好的选择。有时,接口和抽象类可以一起使用,接口中定义函数,而在抽象类中定义默认的实现。

    11. ⼯⼚⽅法模式(利⽤创建同⼀接⼝的不同实例)

    1、普通⼯⼚模式:建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类进⾏实例的创建;

    12.接口是什么?为什么要使用接口而不是直接使用具体类?

    接口用于定义 API。它定义了类必须得遵循的规则。同时,它提供了一种抽象,因为客户端只使用接口,这样可以有多重实现,如 List 接口,你可以使用可随机访问的 ArrayList,也可以使用方便插入和删除的 LinkedList。接口中不允许写代码,以此来保证抽象,但是 Java 8 中你可以在接口声明静态的默认方法,这种方法是具体的。

    13.java中,抽象类与接口之间有什么区别?

    1.一个类可以实现多个接口 ,但却只能继承最多一个抽象类。

    2.抽象类可以包含具体的方法 , 接口的所有方法都是抽象的。

    3.抽象类可以声明和使用字段 ,接口则不能,但接口可以创建静态的final常量。

    4.接口的方法都是public的,抽象类的方法可以是public,protected,private或者默认的package;

    5.抽象类可以定义构造函数,接口却不能。

    14.除了单例模式,你在生产环境中还用过什么设计模式?

    这需要根据你的经验来回答。一般情况下,你可以说依赖注入,工厂模式,装饰模式或者观察者模式,随意选择你使用过的一种即可。不过你要准备回答接下的基于你选择的模式的问题。

    15.什么是里氏替换原则?

    1、开闭原则(Open Close Principle)

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

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

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

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

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

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

    这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

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

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

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

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

    16.什么情况下会违反迪米特法则?为什么会有这个问题?

    迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减少类之间的耦合。

    17.适配器模式是什么?什么时候使用?

    18.适配器模式与装饰器模式有什么区别?

    19.适配器模式和代理模式之间有什么不同?

    20.什么是模板方法模式?

    21.什么时候使用访问者模式?

    22.什么时候使用组合模式?

    23.继承和组合之间有什么不同?

    24.描述Java中的重载与重写?什么时候用重载,什么时候用重写?

    25.Java中,嵌套公共静态类与顶级类有什么不同?

    26.OOP中的组合、聚合和关联有什么区别?

    27.给我一个符合开闭原则的设计模式的例子?

    28.使用工厂模式最主要的好处是什么?你在哪里使用?

    29.工厂模式与抽象工厂模式的区别?

    30.什么是设计模式?你是否在你的代码里面使用过任何设计模式?

    31.你可以说出几个在JDK库中使用的设计模式吗?

    32.Java中什么是单例设计模式?用Java写出线程安全的单例

    33.什么是责任链设计模式?

    下载链接博主已将以上这些面试题整理成了一个面试手册,是PDF版的

    更多相关内容
  • 以落地解决方案为核心,从实际业务中抽离出,交易、营销、秒杀、中间件、源码等22个真实场景,来学习设计模式的运用。 适合人群 1. 具备一定编程基础在工作1-3年的研发人员 2. 希望通过此书提升编码思维,剔除到...
  • 文件类型为PDF文件,此文档对20多种java设计模式进行了详细讲解,在中文讲解的过程中还附有代码示例给学习者进行参考,使学习者通过实践更容易理解设计模式的原理。 本文档目录: 1.工厂模式 2.单例模式 3.建造...
  • Java设计模式深入研究

    2015-08-31 10:41:28
    设计模式是一套被重复使用的代码设计经验的总结,本书面向有一定Java语言基础和一定编程经验的读者。旨在培养读者良好的设计模式思维方式,加强对面向对象思想的理解。全书共分12章,首先强调了接口和抽象类在设计...
  • Java设计模式-工厂模式

    千次阅读 多人点赞 2021-08-06 09:27:36
    Java设计模式-工厂模式 什么是工厂模式? 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会...

    Java设计模式-工厂模式

    什么是工厂模式?

    工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
    在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    简单编写一个类:

    1、简单工厂模式

    interface IFruit{
    	public void eat();	//吃水果
    }
    class Apple implements IFruit{
    	public void eat(){
    		System.out.println("削皮吃苹果!");
    	}
    }
    class Orange implements IFruit{
    	public void eat(){
    		System.out.println("剥皮吃橘子!");
    	}
    }
    public class Factory{
    	public static void main(String args[]){
    		IFruit fruit = new Apple();
    		//削皮吃苹果!
    		fruit.eat();
    	}
    }
    

    本程序非常简单就是通过接口的子类为接口对象实例化,但是本操作存在什么样的问题呢?

    之前一直在强调,主方法或者是主类是一个客户端,客户端的操作应该越简单越好。但是在现在的程序之中,有一个最大的问题:客户端之中,一个接口和一个固定的子类绑在一起了。

    在本程序之中,最大的问题在于耦合上,发现在主方法之中一个接口和一个子类紧密耦合在一起,这种方法比较直接,可以简单的理解为:A→B,但是这种紧密的方式不方便于维护,所以后来使用了A→B→C,中间经历了一个过渡,这样一来B去改变,C去改变,但是A不需要改变,就好比JAVA的JVM一样:程序→JVM→操作系统。

    2、普通工厂模式

    UML图:

    源代码:

    ProjectFactory.java

    public interface ProjectFactory {
    	Project getname();
    }
    

    BlueFactory.java(ConcreteFactory1)

    public class BlueFactory implements ProjectFactory{
    
    	@Override
    	public Project getname() {
    		// TODO Auto-generated method stub
    		return new Bluepen();
    	}
    
    }
    

    RedFactory.java(ConcreteFactory2)

    public class RedFactory implements ProjectFactory{
    
    	@Override
    	public Project getname() {
    		// TODO Auto-generated method stub
    		return new redPen();
    	}
    
    }
    

    Project.java(产品类)

    public interface Project {
    	void name();
    }
    

    Bluepen.java(ConcreteProject1)

    public class Bluepen implements Project{
    
    	@Override
    	public void name() {
    		// TODO Auto-generated method stub
    		System.out.println("这是一个蓝色的笔");
    	}
    
    }
    

    RedFactory.java(ConcreteProject2)

    public class RedFactory implements ProjectFactory{
    
    	@Override
    	public Project getname() {
    		// TODO Auto-generated method stub
    		return new redPen();
    	}
    
    }
    

    测试类

    public class Client {
    	public static void main(String[] args) {
    		Project pen = new RedFactory().getname();
    		pen.name();
    		Project pen1 = new BlueFactory().getname();
    		pen1.name();
    	}
    }
    

    运行结果:

    image-20210805205221818

    这个时候发现客户端不在和一个具体的子类耦合在一起了,就算以后增加了新的子类,那么也只需要修改Factory类即可。

    总结:

    1. 以后如果是自己编写的接口如果想要取得接口的 实例化对象,第一反应写工厂类
    2. 简单工厂和工厂方法模式的不同在于前者生成产生产品的行为封装在一个方法中,根据参数的类型进行实例化,同时不存在抽象接口。而后者则增加了抽象工厂,通过实现不同的工厂方法来创建不同的产品,一个方法通常对应一个产品,这种方式相较于前者扩展性更高,在需求增加时完全符合开闭原则和依赖倒置原则

    使用场景:

    消费者不关心它所要创建对象的类(产品类)的时候。

    消费者知道它所要创建对象的类(产品类),但不关心如何创建的时候。

    例如:hibernate里通过sessionFactory创建session、通过代理方式生成ws客户端时,通过工厂构建报文中格式化数据的对象。

    3、抽象工厂模式

    定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

    抽象工厂模式与工厂方法模式的区别

    ​ 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

    ​ 在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。.

    如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。

    UML图:

    image-20210805210243478

    源代码:

    Factory.java(抽象工厂)

    public interface Factory {
    	PhoneProject projectPhone();
    	LaptopProject projectLaptop();
    }
    

    HuaWeiFactory.java(华为具体工厂)

    public class HuaWeiFactory implements Factory{
    
    	@Override
    	public PhoneProject projectPhone() {
    		// TODO Auto-generated method stub
    		return new HuaWeiPhone();
    	}
    
    	@Override
    	public LaptopProject projectLaptop() {
    		// TODO Auto-generated method stub
    		return new HuaWeiLaptop();
    	}
    
    }
    

    XiaomiFactory.java(小米具体工厂)

    public class XiaomiFactory implements Factory{
    
    	@Override
    	public PhoneProject projectPhone() {
    		// TODO Auto-generated method stub
    		return new XiaomiPhone();
    	}
    
    	@Override
    	public LaptopProject projectLaptop() {
    		// TODO Auto-generated method stub
    		return new XiaomiLaptop();
    	}
    
    }
    

    LaptopProject.java(笔记本产品)

    public interface LaptopProject {
    	void getId();
    	void printInfo();
    }
    

    HuaWeiLaptop.java(华为笔记本)

    public class HuaWeiLaptop implements LaptopProject{
    
    	@Override
    	public void getId() {
    		// TODO Auto-generated method stub
    		System.out.println("编号"+123);
    	}
    
    	@Override
    	public void printInfo() {
    		// TODO Auto-generated method stub
    		System.out.println("生产了华为电脑");
    	}
    
    }
    

    XiaomiLaptop.java(小米笔记本)

    public class XiaomiLaptop implements LaptopProject{
    
    	@Override
    	public void getId() {
    		// TODO Auto-generated method stub
    		System.out.println("编号"+213);
    	}
    
    	@Override
    	public void printInfo() {
    		// TODO Auto-generated method stub
    		System.out.println("生产小米电脑");
    	}
    
    }
    

    PhoneProject.java(手机产品)

    public interface PhoneProject {
    	void getId();
    	void printInfo();
    }
    

    HuaWeiPhone.java(华为手机)

    public class HuaWeiPhone implements PhoneProject{
    
    	@Override
    	public void getId() {
    		// TODO Auto-generated method stub
    		System.out.println("编号:"+123412);
    	}
    
    	@Override
    	public void printInfo() {
    		// TODO Auto-generated method stub
    		System.out.println("生产华为手机");
    	}
    
    }
    
    

    XiaomiPhone.java(小米手机)

    public class XiaomiPhone implements PhoneProject{
    
    	@Override
    	public void getId() {
    		// TODO Auto-generated method stub
    		System.out.println("编号:"+123412);
    	}
    
    	@Override
    	public void printInfo() {
    		// TODO Auto-generated method stub
    		System.out.println("生产了小米手机!!");
    	}
    }
    
    

    测试类:

    public class Client {
    	public static void main(String[] args) {
    		PhoneProject huawei = new HuaWeiFactory().projectPhone();
    		huawei.printInfo();
    		huawei.getId();
    		
    		PhoneProject xiaomi = new XiaomiFactory().projectPhone();
    		xiaomi.printInfo();
    		LaptopProject huawei1 = new HuaWeiFactory().projectLaptop();
    		huawei1.printInfo();
    	}
    }
    

    运行结果:

    image-20210805211054410

    总结:

    抽象工厂模式是工厂方法模式的升级版,后者面向单个产品,而前者面向的的是一个产品族。根据官方定义:为创建一组相关/互相依赖的对象提供一个接口而无需指定它们的具体类。
    比如一个汽车工厂要生成骑车,而每种汽车都有车门、车轮胎等一系列产品,这意味着每增加一款汽车就需要增加一个新的工厂来提供新产品的实现。这时候就可以使用抽象工厂模式来进行设计。抽象工厂模式适用于一系列产品族。

    优点:

    1. 抽象厂模式将产品族的依赖与约束关系放到抽象工厂中,便于管理。
    2. 职责解耦,用户不需要关心一堆自己不关心的细节,由抽象厂来负责组件的创建
    3. 切换产品族容易,只需要增加一个具体工厂实现,客户端选择另-个套餐就可以了

    缺点:

    1. 抽象工厂模式类增加的速度很快,有一个产品族就需要增加一一个具体工厂实现,比较繁琐
    2. 产品族难以扩展产品。当产品族中增加一个产品时,抽象工厂接口中需要增加一个函数,对应的所有具体工厂实现都需要修改,修改放大严重。
    3. 抽象厂并未完全屏蔽创建细节,给出的都是组件。对于这种情况可以结合工厂模式或简单工厂模式-起使用。

    使用场景:

    大家应该已经发现了,其实抽象工厂模式如果只有一个组件的话,其实是退化到工厂方法模式,也就是没有了产品族的概念,只剩一一个产品了,因此简单工厂,厂方法,抽象工厂这三者之间是有内在联系的,区别只产品的复杂度。抽象工厂的本质是选择产品族,因此大家可以根据这个特征来识别是否可以应用抽象厂。

    展开全文
  • Java设计模式之行为型:中介者模式

    万次阅读 2021-09-14 17:52:27
    中介者模式通过中介者对象来封装一系列的对象交互,将对象间复杂的关系网状结构变成结构简单的以中介者为核心的星形结构,对象间一对多的关联转变为一对一的关联,简化对象间的关系,便于理解;各个对象之间的关系被...

     前言:

            在我们的生活中处处充斥着“中介者”,比如你租房、买房、找工作、旅游等等可能都需要那些中介者的帮助,地球上国与国之间的关系异常复杂,会因为各种各样的利益关系来结成盟友或者敌人,国与国之间的关系同样会随着时间、环境因为利益而发生改变,而地球上最大的中介者就是联合国了,它主要用来维护国际和平与安全、解决国际间经济、社会、文化和人道主义性质的问题。软件开发过程也同样如此,对象与对象之间存在着很强、复杂的关联关系,如果没有类似于联合国这样的“机构”会很容易出问题的,譬如:

    • (1)系统的结构变得很复杂,对象与对象之间存在大量的关联,若一个对象发生改变,与之关联的对象也需要做出相应的处理。
    • (2)对象之间的连接增加导致对象可复用性降低
    • (3)系统的可扩展性低,增加一个新对象,我们需要在其相关连的对象上面加上引用,这样就会导致系统的耦合性增高,使系统的灵活性和可扩展都降低。

            如果两个类不必彼此通信,那么这两个类就不应当发生直接关联的关系,如果一个类需要调用另一个类中的方法,我们可以通过第三方来转发这个调用。所以对于关系比较复杂的系统,为了减少对象之间的关联关系,使之成为一个松耦合系统,我们就需要使用中介者模式。

    一、什么是中介者模式:

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

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

    二、UML结构图:

    • Mediator:抽象中介者,定义了同事对象到中介者对象之间的接口
    • ConcreteMediator:具体中介者,实现抽象中介者的方法,它需要知道所有的具体同事类,同时需要从具体的同事类那里接收信息,并且向其他具体的同事类发送信息
    • Colleague:抽象同事类
    • ConcreteColleague:具体同事类,每个具体同事类都只需要知道自己的行为即可,但是他们都需要认识中介者。

    从UML结构类图中可以看出,在系统中,中介者类主要承担中转和协调两个方面的责任:

    • 结构上起到中转作用:通过中介者类对关系的封装,使得对象类不再需要显示的引用其他对象,只需要通过中介者就可以与其他对象类进行的通信。
    • 行为上起到协调作用:通过中介者类对关系的封装,对象类可以在不知道其他对象的情况下通过中介者与其他对象完成通信。在这个过程中对象类是不需要告诉中介者该如何做,中介者可以根据自身的逻辑来进行协调,对同事的请求进一步处理,将同事成员之间的关系行为进行分离和封装。

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

            最后,中介者模式也比较容易被误用,故当系统中出现了“多对多”交互复杂的关系群时,千万别急着使用中介者模式,你首先需要做的就是反思你的系统在设计上是不是合理。

    三、代码实现:

    我们就以租房为例,中介机构充当租房者与房屋所有者之间的中介者。

    首先是抽象中介者:Mediator.java

    public abstract class Mediator {
        //申明一个联络方法
        public abstract void constact(String message,Person person);
    }
    

    然后是抽象同事对象:Person.java

    public class HouseOwner extends Person{
     
        HouseOwner(String name, Mediator mediator) {
            super(name, mediator);
        }
        
        /**
         * @desc 与中介者联系
         * @param message
         * @return void
         */
        public void constact(String message){
            mediator.constact(message, this);
        }
     
        /**
         * @desc 获取信息
         * @param message
         * @return void
         */
        public void getMessage(String message){
            System.out.println("房主:" + name +",获得信息:" + message);
        }
    }
    

     Tenant.java

    public class Tenant extends Person{
        
        Tenant(String name, Mediator mediator) {
            super(name, mediator);
        }
        
        /**
         * @desc 与中介者联系
         * @param message
         * @return void
         */
        public void constact(String message){
            mediator.constact(message, this);
        }
     
        /**
         * @desc 获取信息
         * @param message
         * @return void
         */
        public void getMessage(String message){
            System.out.println("租房者:" + name +",获得信息:" + message);
        }
    }
    

    具体中介者对象:中介结构、MediatorStructure.java

    public class MediatorStructure extends Mediator{
        //首先中介结构必须知道所有房主和租房者的信息
        private HouseOwner houseOwner;
        private Tenant tenant;
     
        public HouseOwner getHouseOwner() {
            return houseOwner;
        }
     
        public void setHouseOwner(HouseOwner houseOwner) {
            this.houseOwner = houseOwner;
        }
     
        public Tenant getTenant() {
            return tenant;
        }
     
        public void setTenant(Tenant tenant) {
            this.tenant = tenant;
        }
     
        public void constact(String message, Person person) {
            if(person == houseOwner){          //如果是房主,则租房者获得信息
                tenant.getMessage(message);
            }
            else{       //反之则是获得房主信息
                houseOwner.getMessage(message);
            }
        }
    }
    

    客户端:Client.java

    public class Client {
        public static void main(String[] args) {
            //一个房主、一个租房者、一个中介机构
            MediatorStructure mediator = new MediatorStructure();
            
            //房主和租房者只需要知道中介机构即可
            HouseOwner houseOwner = new HouseOwner("张三", mediator);
            Tenant tenant = new Tenant("李四", mediator);
            
            //中介结构要知道房主和租房者
            mediator.setHouseOwner(houseOwner);
            mediator.setTenant(tenant);
            
            tenant.constact("听说你那里有三室的房主出租.....");
            houseOwner.constact("是的!请问你需要租吗?");
        }
    }
    

    运行结果:

    房主:张三,获得信息:听说你那里有三室的房主出租..... 
    租房者:李四,获得信息:是的!请问你需要租吗?


    设计模式系列文章:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


    文章总结自:设计模式读书笔记-----中介者模式_chenssy 的技术博客-CSDN博客

    展开全文
  • 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之美[从菜鸟到高手演变]之设计模式四

    展开全文
  • Java设计模式——策略模式

    万次阅读 多人点赞 2021-10-29 12:50:37
    策略模式 1.策略模式简介 策略模式:策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口 和 具体行为的实现。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解...
  • Java 设计模式 --- Builder模式 Java Builder 模式 一、Builder模式 1、builder模式也叫建造者模式,builder模式的作用将一个复杂对象的构建与他的表示分离,使用者可以一步一步的构建一个比较复杂的对象。 2...
  • Java设计模式-代理模式

    千次阅读 多人点赞 2021-08-06 11:02:40
    Java设计模式-代理模式 什么是代理模式? 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 ...
  • 目录 文章目录目录一、前言二、简介1. 谁发明了设计模式?2. 我怎么学不会设计模式?...5月20日那天投身实战型设计模式打磨,通过模拟互联网业务开发实际需求作为学习场景,讲解设计模式。 全书共计22个真实业务场
  • Java设计模式pdf

    千次阅读 多人点赞 2020-06-26 14:52:00
    Java设计模式PDF下载PDF简述下载链接PDF图片 PDF简述 全PDF共分27章,内容包括统一建模语言基础知识、面向对象设计原则、设计模式概述、简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式...
  • 工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:简单工厂模式、工厂...当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,保证客户端始终只使用同一个产品族
  • Java设计模式-模板模式

    千次阅读 多人点赞 2021-08-05 11:19:49
    Java设计模式-模板模式 什么是模板模式? 模板模式,顾名思义,就是通过模板拓印的方式。 定义模板,就是定义框架、结构、原型。定义一个我们共同遵守的约定。 定义模板,我们的剩余工作就是对其进行充实、丰润,...
  • 单例模式:确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。 public class Singleton{ private static Singleton instance = null;//静态私有成员变量 //私有构造函数 private Singleton()...
  • 单例设计模式分为二种:饿汉式和懒汉式 单例设计模式的优点: 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的 产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可 以通过在应用...
  • Java设计模式—观察者模式

    千次阅读 2021-09-21 16:57:24
    前言:在现实世界中,许多对象并...MVC 模式中的模型与视图的关系;事件模型中的事件源与事件处理者。所有这些,如果用观察者模式来实现就非常方便。 一、观察者模式简介 1.1、观察者模式概述 观察者模式(Observer
  • JAVA设计模式之单例模式

    万次阅读 多人点赞 2014-04-16 06:51:34
     java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的...
  • Java设计模式实战 ~ 总目录

    千次阅读 2019-09-17 16:41:50
    本文主要是对前段时间研究设计模式和面向对象设计原则做一个总结归纳
  • Java设计模式:状态机模式

    千次阅读 2019-04-21 23:33:13
    public class State { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public void method1() {... System.out.pri...
  • JAVA设计模式学习【技术文档】

    千次下载 热门讨论 2014-01-08 14:50:55
    JAVA设计模式的一个基础介绍,适合对java学习感兴趣的人士参考,129页,doc格式。
  • Java设计模式--责任链模式--使用/详解/实例

    千次阅读 多人点赞 2021-06-29 13:08:29
    原文网址:Java设计模式--责任链模式--使用/详解/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍Java设计模式中的责任链模式的一些场景。 责任链模式的好处 符合单一职责原则 每个功能都作为链路上的一个节点 ...
  • Java设计模式

    千次下载 热门讨论 2007-02-07 09:15:12
    Java设计模式
  • java设计模式(第二版)(含源代码)

    热门讨论 2013-10-22 23:09:58
    JAVA设计模式,John Metsker的经典著作。一本非常不错的书!是中文版图书,已经是第二版了,2012年出版,随书的源代码一并提供,方便你的学习。
  • Java设计模式-单例模式实际应用场景

    千次阅读 2021-01-02 10:19:41
    单例模式应用的场景 单例模式应用的场景一般发现在以下条件下: 资源共享的情况下,避免由于资源操作时导致的性能或损耗等,如日志文件,应用配置。 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个...
  • java设计模式

    千次阅读 2018-07-12 13:49:41
    一、工厂模式创建一个 Shape 接口和实现 Shape 接口的实体类。下一步是定义工厂类 ShapeFactory。1、创建一个接口:Shape.javapublic interface Shape { void draw();}2、创建实现接口的实体类。Rectangle.java...
  • java 设计模式.pdf 免费下载

    千次阅读 2019-07-17 22:35:09
    ** 下载链接 **
  • java设计模式,百度网盘

    千次阅读 2016-09-24 20:50:23
    java设计模式.pdf /资料/java设计模式.pdf 分享时间:2016-07-23 19:23分享用户:Ba***012文件大小:2MB文件类型:pdf 23种java设计模式.pdf /JAVA设计模式/23种java设计模式.pdf 分享时间:2015-07-31 10:41...
  • Java设计模式之行为型:命令模式

    万次阅读 2018-11-04 10:16:56
    命令模式的本质是将请求封装成对象,将发出命令与执行命令的责任分开,命令的发送者和接收者完全解耦,发送者只需知道如何发送命令,不需要关心命令是如何实现的,甚至是否执行成功都不需要理会。命令模式的关键在于...
  • Java设计模式——单一职责模式

    千次阅读 2018-05-23 10:22:20
    今天和大家聊一聊单一职责模式,大家从名字应该就能想到这个设计模式的核心思想就是降低耦合性,强调一个类/整体只做一件事。今天就不给大家代码举例子了,因为这个会很好理解,你只要写一个类,强调一个方法,方法...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,048,905
精华内容 419,562
关键字:

java 设计模式

友情链接: ABC.rar