设计模式
说一说设计模式的六大原则
单一职责原则
一个类,应当只有一个引起它变化的原因;即一个类应该只有一个原则。
就一个类而言,应该只专注于做一件事和仅有一个引起变化的原因,着就是所谓的单一职责原则。该原则提出了对对象职责的一种理想状态,对象不应该承担太多职责,正如人不应该一心分为二用。唯有专注,才能保证对象的高内聚;唯有单一才能保证对象的细粒度。对象的高内聚和细粒度有利于对象的重用。
里氏替换原则
所有引用基类的地方必须能透明地使用其子类对象。清晰明确的说明只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误和异常,使用者可以根本就不需要知道是父类还是子类;但是反过来不可以,有子类的地方,替换为父类就未必适应。
依赖倒置原则
在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是具体的实现类,实现类实现了接口或者继承了抽象类,其特点是可以直接被实例化的。依赖倒置原则在Java语言中的表现是:
(1)模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生;
(2)接口或抽象类不依赖于实现类;
(3)实现类依赖于接口或抽象类。
依赖倒置原则更加精确的定义就是”面向接口编程“————OOD(Object-Oriented Design)的精髓之一。依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。依赖倒置原则是JavaBean,EJB和COM等组件设计模型背后的基本原则。
接口隔离原则
接口隔离原则有如下两种定义:
(1)客户端不应该依赖它不需要的接口;
(2)类间的依赖关系应该建立在最小的接口上。
接口隔离原则的具体含义如下:
(1)一个类对另外一个类的依赖性应当是建立在最小的接口上。
(2)一个接口代表一个角色,不应当将不同的角色都交给一个接口。
(3)不应该强迫客户依赖于他们不用的方法。
迪米特法则
迪米特法则又称为最少知识原则,意思是一个对象应当对其他对象尽可能少的了解。迪米特法则不同于其他的OO设计原则,它具有很多的表述方式:
(1)只与你直接的朋友们通信;
(2)不要跟”陌生人说话“;
(3)每个软件单位对其他的单位都只有最少的了解,这些了解仅局限于那些与本单位密切相关的软件单位。
按照迪米特法则,如果两个类不必彼此直接通信,那么两个类就不应当发生直接的相互作用;如果一个类需要调用另一个类的某个方法,可以通过第三者转发这个调用。
开闭原则
开闭原则的定义是:一个软件实体应当对扩展开放,对修改关闭。在设计一个模块的时候,应当使这个模块在可以不被修改的前提下被扩展,即应当可以在不必修改源代码的情况下改变这个模块的行为。
设计模式分类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
创建型模式
工厂模式
定义:定义了一个创建对象的类,由这个类来封装实例化对象的行为。
工厂模式的用意是定义一个创建对象的工厂接口,将实际创建性工作推迟到子类中。工厂模式可以分为简单工厂、工厂方法和抽象工厂模式。注意,我们常说的23种经典设计模式,包含了工厂方法模式和抽象工厂模式,而并未包含简单工厂模式。
简单工厂
简单工厂模式其实并不是一种设计模式,更多的时候是一种编程习惯。简单工厂的实现思路是,定义一个工厂类,根据传入参数的不同返回不同的实例,被创建的实例具有共同的父类或接口。

为工厂类传入不同的type可以new不同的形状,返回结果为shape类型,这个就是简单工厂核心的地方了。
工厂方法
工厂方法模式是简单工厂的进一步深化,在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。工厂方法的实现思路是,定义一个用于创建对象的接口,让子类决定将哪一个实例化。
和简单工厂对比一下,最根本的区别在于,简单工厂只有一个统一的工厂类,而工厂方法是针对每个要创建的对象都会提供一个工厂类,这些工厂类都实现了一个工厂基类。
抽象工厂
这个模式最不好理解,而且在实际应用中局限性也蛮大的,因为这个模式并不符合开闭原则。实际开发还需要做好权衡。抽象工厂模式是一个工厂方法的进一步深化,这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象,这是和工厂方法最大的不同点。
抽象工厂的实现思路是,提供一个创建一些列相关或相互依赖对象的接口,而无需指定他们具体的类。抽象工厂和工厂方法一样可以划分为4大部分。

简单工厂模式和抽象工厂模式的区别
(多个工厂,一个工厂可以创建一组对象)
简单工厂模式就是建立一个实例化对象的类,在该类中对多个对象实例化。工厂方法模式是定义了一个创建对象的抽象方法,由子类决定要实例化的类。这样做的好处是再有新的类型的对象需要实例化只要增加子类即可。抽象工厂模式定义了一个接口用于创建对象族,而无需明确指定具体类。抽象工厂也是把对象的实例化交给了子类,即支持拓展。同时提供给客户端接口,避免了用户直接操作子类工厂。
单例模式
定义:确保一个类最多只有一个实例,并提供一个全局访问点
单例模式可以分为两种:预加载和懒加载
饿汉式单例模式
public class Singleton { private static Singleton instance = new Singleton(); //私有构造方法,保证外界无法直接实例化 private Singleton(){} //通过公有静态方法获取实例对象 public static Singleton getInstance(){ return instance; } }
懒汉式单例模式
public class Singleton { private static Singleton instance = null; //私有构造方法,保证外界无法直接实例化 private Singleton(){} //通过公有静态方法获取实例对象 public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
线程安全的单例模式
public class Singleton { private static Singleton instance = null; //私有构造方法,保证外界无法直接实例化 private Singleton(){} //通过公有静态方法获取实例对象 synchronized public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
单例模式优点:
(1)在单例模式中,活动的单例只有一个实例,对单例的所有实例化得到的都是相同的一个实例。这样就,防止其他对象对自己的实例化,确保所有对象都访问一个实例。
(2)提供了对唯一实例的受控访问。
(3)由于系统内存中只存在一个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
(4)避免对共享资源的多重占用。
缺点:
(1)不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
(2)由于单例模式没有抽象层,因此单例类的扩展有很大的困难。
(3)单例类的职责过重,在一定程度上违背了”单一职责原则‘。
(4)使用时不能用反射模式创建单例,否则会实例化一个新的对象。
生成器模式
定义:封装一个复杂对象构造过程,并允许按步骤构造。
定义解释: 我们可以将生成器模式理解为,假设我们有一个对象需要建立,这个对象是由多个组件(Component)组合而成,每个组件的建立都比较复杂,但运用组件来建立所需的对象非常简单,所以我们就可以将构建复杂组件的步骤与运用组件构建对象分离,使用builder模式可以建立。
优点:
-
将一个对象分解为各个组件
-
将对象组件的构造封装起来
-
可以控制整个对象的生成过程
-
对不同类型的对象需要实现不同的具体构造器的类,这可能回答大大增加类的数量
生成器模式与工厂模式的不同
生成器模式构建对象的时候,对象通常构建的过程中需要多个步骤,就像我们例子中的先有主机,再有显示屏,再有鼠标等等,生成器模式的作用就是将这些复杂的构建过程封装起来。工厂模式构建对象的时候通常就只有一个步骤,调用一个工厂方法就可以生成一个对象。
原型模式
定义:通过复制现有实例来创建新的实例,无需知道相应类的信息。
简单地理解,其实就是当需要创建一个指定的对象时,我们刚好有一个这样的对象,但是又不能直接使用,我会clone一个一模一样的新对象来使用;基本上这就是原型模式。关键字:Clone。
原型模式的本质就是clone,可以解决构建复杂对象的资源消耗问题,能再某些场景中提升构建对象的效率;还有一个重要的用途就是保护性拷贝,可以通过返回一个拷贝对象的形式,实现只读的限制。
结构型模式
适配器模式
定义: 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。
主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。
类适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。
对象适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就行。
接口适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写别的类的时候,继承抽象类即可。
装饰者模式
定义:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
装饰者和被装饰者之间必须是一样的类型,也就是要有共同的超类。在这里应用继承并不是实现方法的复制,而是实现类型的匹配。因为装饰者和被装饰者是同一个类型,因此装饰者可以取代被装饰者,这样就使被装饰者拥有了装饰者独有的行为。根据装饰者模式的理念,我们可以在任何时候,实现新的装饰者增加新的行为。如果是用继承,每当需要增加新的行为时,就要修改原程序了。
代理模式
定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。
代理模式分为三类:1. 静态代理 2. 动态代理 3. CGLIB代理
外观模式
定义: 隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。
- 松散耦合
使得客户端和子系统之间解耦,让子系统内部的模块功能更容易扩展和维护;
- 简单易用
客户端根本不需要知道子系统内部的实现,或者根本不需要知道子系统内部的构成,它只需要跟Facade类交互即可。
- 更好的划分访问层次
有些方法是对系统外的,有些方法是系统内部相互交互的使用的。子系统把那些暴露给外部的功能集中到门面中,这样就可以实现客户端的使用,很好的隐藏了子系统内部的细节。
桥接模式
定义: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
优点:
(1)在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
(2)桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。
缺点:
桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
Spring框装架中用到了哪些设计模式?

浙公网安备 33010602011771号