一、单例模式
单例模式属于创建型模式,解决某个类频繁的创建与销毁。该模式保证了其对象在中只有一个实例对象存在。必须保证私有化构造函数,只能有一个实例对象存在。
优点:
- 减少关键字的使用,降低系统内存的使用频率,同时减轻工作
- 避免了资源的多重使用
缺点:
- 不可继承,没有接口。
1、饿汉式
- 优点:没有加锁同步,执行效率高
- 缺点:当类加载时就初始化,没有懒加载,浪费内存。通过classloader 机制避免了多线程的同步问题
HungrySingleton.java
讯享网2、懒汉式
实现方式(1)
- 优点:实现懒加载,实例化对象是在调用后
- 缺点:没有加锁 ,多线程下使用存在问题
LazySingleton.java
讯享网
实现方式(2)
- 改进:增加 关键字,解决多线程问题
- 不足:锁住了这个对象,每次调用都会对对象上锁,这样大大降低了性能,事实上我们只有在第一次为空时才需要加锁
SyncLazySingleton.java
实现方式(3)(双重检测)
- 该进:对做了判断,只有当为空时才对对象加锁,提升性能
- 不足:依然存在小点问题(无序写入问题),例如:
- 1、线程1、线程2进入
- 2、线程1首先进入线程同步,线程2等待线程1执行完成
- 3、线程1判断为空则分配地址内存空间并实例化该类对象
- 4、线程1执行完成退出
- 5、线程2进入同步,此时已被线程1实例化,不为空,则返回线程1创建的instance实例。
- 由于无序写入问题,导致线程2有可能返回
SyncLazySingleton2.java
讯享网
3、静态内部类
- 优点:懒加载策略,线程安全。利用classloader加载机制实现初始化时只有一个线程,当被加载时,instance不一定被初始化,应为没有调用SingleFactory没有被主动调用
- 缺点:如果在构造函数中抛出异常,则将得不到实例
InnerSingleton .java
3、枚举实现
枚举详情参考
- 过关键字创建枚举类型在编译后生成一个继承自类的类和另外一个类,其中是抽象类,编译器还为我们生成了两个静态方法,分别是和 ,values()方法的作用就是获取枚举类中的所有变量,并作为数组返回,而方法与类中的方法的作用类似根据名称获取枚举变量,上述两个方法需枚举实例向上转型为。
- 使用枚举单例的写法,我们完全不用考虑序列化和反射的问题。枚举序列化是由保证的,每一个枚举类型和定义的枚举java几种基础模式变量在中都是唯一的,在枚举类型的序列化和反序列化上,做了特殊的规定:在序列化时仅仅是将枚举对象的属性输出到结果中,反序列化的时候则是通过的方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的并禁用了、、、和等方法,从而保证了枚举实例的唯一性。
- 优点:线程安全,支持序列化机制,实现单例模式**做法(少数使用)
- 缺点:未实现懒加载
实现结果图

二、工厂模式
特点:
- 提供一种创建对象的**方式,在创建对象时不提供对外暴露创建逻辑,并且通过一个共同的接口来指向新创建的对象
- 定义一个创建对象的接口,让子类来决定实例化哪一个具体的工厂类,延迟到子类去执行
- 主要解决选择接口的问题
- 扩展性高,只增加相应工厂类即可,知道名称即可创建对象,屏蔽具体的实现,调用者只关心接口
- 增加需求时,需要增加具体类与工厂实现,导致类个数成倍增加,增加系统复杂度
- 只有需要生成复杂类对象时才需要使用工厂模式,且简单工厂模式不属于23种设计模式
(1)、简单工厂
PersonAction.java
WomanFactory .java
ManFactory.java
PersonFactory 工厂类
使用如下
(2)、多个方法
修改PersonFactory.java如下
(3)、静态方法
修改PersonFactory.java如下
直接可通过类名调用方法
1、工厂方法模式
PersonAction.java
WomanEat.java
ManEat.java
Provider.java
WomanFactory .java
ManFactory.java
具体使用如下:
2、抽象工厂方法模式
自己简化版
LandAnimal.java
WaterAnimal .java
Cat .java
Dog .java
Fish .java
Shark .java
AbstractFactory .java
AnimalFactory.java
使用方法如下:
三、建造者模式(Builder)
特点:
- 在需要生成复杂内部结构时使用,即将多个简单的对象一步一步构建称为一个复杂对象。
构建方式(1)
新建Person.java类
新建构造(builder)类PersonBuilder .java
使用如下:
看到这里是不是与构建对话框与OKHTTP3类似呢?

构建方式(2)
新建Person.java类
Ibuilder.java
ImplBuilder.java
使用如下:
四、适配器模式
特点:
- 适配器继承或依赖已有的对象,实现想要的目标接口
- 消除由于接口不匹配所造成的类的兼容性问题
- 类的适配器模式、对象的适配器模式、接口的适配器模式
- 提高了类的复用,增加了类的透明度
(1)类的适配器模式
通过实现目标接口,继承原有类,在原有类的基础上增加接口中方法,将一个类转换成满足另一个新接口的类
Original.java
ExpandInterfacen .java
NewAdapter .java
使用如下

(2)对象的适配器模式

不继承原有类,而是持有该类实例来实现兼容,将一个对象转换成满足另一个新接口的对象
ObjectAdapter.java
使用如下
(3)接口的适配器模式
不希望实现一个接口中所有的方法,可选择一个抽象类实现接口,然后继承该抽象类实现想实现的方法即可
ExpandInterfacen.java
AbstractInterface.java
Expand.java
五、装饰器模式
特点:装饰类持有原有类或接口的对象,并调用它的方法
- 通过一个装饰类对现有类对象动态添加一些功能,同时不改变其结构
- 动态添加,动态撤销
- 继承的替代方式,继承只能静态添加
- 多成装饰产生过多相似对象,复杂且不易排错
这两参考了两种写法
(1)一个装饰类
Person,java
吃饭Petter.java
装饰类PetterDecorator.java,饭前洗手,饭后睡觉
使用如下:
运行结果
(2)抽象装饰,多个装饰类
Component抽象构件——Animal.java
ConcreteComponent 具体构件——Dog.java
ConcreteComponent 具体构件——Fish.java
Decorator装饰角色(一般为抽象类)——AbDecoratorAnimal.java
具体装饰角色——DogDecorator.java
具体装饰角色——DogDecorator2.java
具体装饰角色——FishDecorator.java
使用如下:
运行结果:
更多详细内容可参考java的 流
我们来看一个实际案例吧!!!更好体验装饰器模式,参考设计模式|菜鸟教程
Hero.java
BlindMonk.java
SkillDecorator.java
Qdecoraotr.java
Wdecoraotr.java
Edecoraotr.java
Rdecoraotr.java
使用如下:
运行结果
六、代理模式
注意事项:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
解决问题:
- 对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问,直接访问会给使用者或者系统结构带来很多麻烦
- 租客 —— 中介 —— 房东
ProxyInterface.java
Tenant.java
AgentProxy.java
使用如下:
七、原型模式
注意事项:
用于创建重复的对象,同时又能保证性能
通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写 clone(),深拷贝是通过实现 Serializable 读取二进制流。
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。
浅复制
深复制
八、备忘录模式
特点:
- 提供了一种可以恢复状态的机制
- 实现了信息的封装,使得用户不需要关心状态的保存细节
- 不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态
原始数据类Original.java
备忘录类Memo.java
保存备忘录类SaveMemo.java
使用方式如下:
运行结果
九、观察者模式
特点
- 类和类之间的关系
- 对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
Observer.java
Observerable1.java
Observerable2.java
Subject.java
AbstractSubject.java
这里写为抽象主要是为了展示扩展思路
RealizeSubject.java
使用方式如下:
实现结果
十、策略模式
特点
- 多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护
- 在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为
- 缺点:策略类会增多,所有策略类都需要对外暴露
Function.java
Addiction.java
Subtraction.java
Division.java
Multiplication.java
Execute.java
使用如下:
本文只阐述常用的几种设计模式,如有其它需求,见下连接
更多设计模式内容请移步:
http://www.runoob.com/design-pattern/design-pattern-tutorial.html 设计模式|菜鸟教程
https://www.cnblogs.com/geek6/p/3951677.html23种设计模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/1602.html