设计模式简单汇总
创建型模式
静态工厂方法模式(Factory、Product、ConcreteProduct)
优缺点:抽象工厂制作,不需要知道产品细节;单一工厂制造产品,风险大
组成:
Factory(抽象类)
Product(抽象类,指定产品配方)
ConcreteProduct_A(具体产品类,继承自Produce)
ConcreteProduct_B(具体产品类,继承自Produce)
Factoryfactory=newFactory();
factory.createProducteA();
factory.createProducteB();
抽象工厂方法模式(Factory、ConcreteFactory、Product、ConcreteProduct)
优缺点:抽象工厂,产出产品族,分担风险,各司其职;增加类的个数,维护变难
组成:
Factory(接口,定义需要制作的规则)
ConcreteFactory_A(实现了Factory接口,制造A产品的规则,假如A产负责生产OPPO手机)
ConcreteFactory_B(实现了Factory接口,制造A产品的规则,假如A产负责生产ViVO手机)
Product(抽象类,抽象产品的定义)
ConcreteProduct_A_C(具体的产品,假如是 OPPO 手机的屏幕)
ConcreteProduct_B_C(具体的产品,假如是 ViVO 手机的屏幕)
ConcreteProduct_A_D(具体的产品,假如是 OPPO 手机的电池)
ConcreteProduct_B_D(具体的产品,假如是 ViVO 手机的电池)
建造者模式(Builder、ConcreteBuilder、Director、Product)
优缺点:只需要关注具体建造者,不必关注产品内部;适合产品内部细节不会太多变化,例如:1.人物换装,2.地图天气变化等
组成:
Builder(抽象类,确认了产品制作的规则,例如:需要各个零件拼接)
ConcreteBuilder (普通Class,1. 继承自 Builder,2. 构造函数,初始化产品类,3. 重写规则方案,修改产品内容)
Director指挥者 (普通Class,指挥者角色,拥有Builder参数,调用Builder方法,可以不存在)
Product (普通Class,存在具体的属性以及getter、setter方法)
工厂模式 和 建造者模式的 区别:
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品
那么建造者模式就是一个 汽车组装工厂 ,通过对部件的组装可以返回一辆完整的汽车
单例模式
优缺点:单例创建对象,节约资源
特点:私有构造函数(自己创建实例)、静态私有成员变量(只有一个实例)、静态公有的工厂方法(暴露实例)
饿汉单例模式(线程安全,不管样都创建,容易产生垃圾):
publicstaticSingletoninstance=newSingleton();
……
publicstaticSingletongetInstance() {
returninstance;
}
懒汉单例模式(线程不安全):
privatestaticSingletoninstance;
……
publicstaticSingletongetInstance() {
if(instance==null) {
instance=newSingleton();
}
returninstance;
}
双重检查单例模式(JDK5版本以上使用,volatile)
privatevolatilestaticSingletoninstance;
……
publicstaticSingletongetInstance() {
/**
* 第一次检查,防止不必要的加锁
*/
if(instance==null) {
synchronized(Singleton.class) {
/**
* 第二次检查,
* 1. 针对指令重排,A线程可能只new了对象,只分配了内存地址,创建空对象,没有给对象赋初始值;解锁
* 2. B线程等A线程解锁后,也进入了这个逻辑,先确认实例是否已经被A线程创建,因为volatile能看到对象状态
*/
if(instance==null) {
instance=newSingleton();
}
}
}
returninstance;
}
这种模式并不安全,对于JVM而言,它执行的是一个个Java指令。
在Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。
但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。
即先赋值指向了内存地址,再初始化)这样就使出错成为了可能,我们仍然以A、B两个线程为例:
A、B线程同时进入了第一个if判断
A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();
由于JVM内部的优化机制,JVM先划出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块
B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序
此时B线程打算使用Singleton实例,却发现它没有被初始化,于是错误发生了
内部类单例模式(安全、不常用)
publicclassSingleton{
privateSingleton(){
…
}
privatestaticclassSingletonContainer{
privatestaticSingletoninstance=newSingleton();
}
publicstaticSingletongetInstance(){
returnSingletonContainer.instance;
}
}
结构型模式
适配器模式(Target、Adaptee、Adapter、Client)
将原有的功能扩展,修改;类似转接头
Target(接口类型,制定规则)
Adaptee(普通Class,被适配者,有自己的方法)
Adapter(普通Class,适配者: 1.继承Adaptee,2.构造方法包含 adaptee,3.重写Adaptee的方法)
Targettarget=newAdaptee();
Targettarget=newAdapter();
两个对象中,Adapter会多一种方法,更加适配类似转接头
桥接模式(Abstraction、RefinedAbstraction、Implementor、ConcreteImplementor)
组合对象模式
Abstraction( 抽象类,构造函数中携带 Implementor 参数,并且定义抽象方法)
RefinedAbstraction_A(继承自Abstraction,说明它是一个维度,并实现抽象规则方法)
RefinedAbstraction_B(继承自Abstraction,说明它是一个维度,并实现抽象规则方法)
Implementor(接口类,有自己的规则;几分糖接口)
ConcreteImplementor_A(实现 Implementor,可以定义: 3分、5分糖的实现类)
ConcreteImplementor_B(实现 Implementor,可以定义: 3分、5分糖的实现类)
使用方:只要 Coffee coffee = new LargeCupCoffee(new FiveSugar());
装饰模式(Component、ConcreteComponent、Decorator、ConcreteDecorator)
扩展对象的功能,比继承灵活
Component(接口,定了规则)
ConcreteComponent(具体实现类,实现了Component)
Decorator(抽象类,1. 实现了 Component,2.构造函数,持有Component,3.抽象方法,调用 Component)
ConcreteDecoratorA (继承了 Decorator, 重写方法)
ConcreteDecoratorB(继承了 Decorator,重写方法)
ComponentconcreteComponent=newConcreteComponent();
ComponentcomponentA=newConcreteDecoratorA(newConcreteComponent());
ComponentcomponentB=newConcreteDecoratorB(newConcreteComponent());
外观模式(Facade、SubSystem)
子系统非常复杂,开发新功能,依赖原有代码;违背“开闭原则”
Facade(统一的门面类)
SubSystem(子系统类)
享元模式(Flyweight、ConcreteFlyweight、UnsharedConcreteFlyweight、FlyweightFactory)
减少内存中对象的数量,
Flyweight: 抽象享元类
ConcreteFlyweight: 具体享元类
UnsharedConcreteFlyweight: 非共享具体享元类
FlyweightFactory: 享元工厂类(map<String, Flyweight>),利用map来缓存
代理模式(Subject、Proxy、RealSubject)
通过中间代理,来做桥联;利于耗时请求延迟处理
Subject: (抽象类,request方法)
Proxy: (继承Subject,afterRequest、preRequest、request方法)
RealSubject: (继承Subject,request方法)
动态代理:
jdk:必须存在抽象的服务类(interface)
1. Proxy.newProxyInstance(classLoader, interface, invokeHandler(proxy, method, args))
cglib:可以不需要抽象的服务类,只需要存在实体类就行
1. Enhancer(实例化工具) , 2. 设置父类对象(Class类型)3. 回调函数, 4. 创建代理
行为型模式
命令模式(Command、ConcreteCommand、Invoker、Receiver)
宏命令,请求调用、请求接收解耦; 可能存在很多具体命令实现类
Command(接口,定义了可执行的命令,如:开、关)
ConcreteCommand(具体实现类,1. 实现了Command接口,2. 携带了接收者,Receiver)
Receiver(接收者,1. 具体实现方法)
Invoker(调用者,1.携带具体具体操作类,这样就控制了最终观察者)
中介者模式(Mediator、ConcreteMediator、Colleague、ConcreteColleague)
处理集中在具体中介者,各个对象之间的关系解耦
Mediator:( 抽象类,抽象中介者,1. 定义抽象方法,并注入 Colleague )
ConcreteMediator:(具体中介者, 1. 继承Mediator,2. 注入具体同事类, 3. 实现抽象方法,采用不同的同事类)
Colleague:(抽象类,抽象同事类,1.定义抽象方法,2. 构造函数,注入Mediator, 3.定义抽象,通知方法)
ConcreteColleague:(具体同事类,1. 注入Mediator, 2.重写通知方法,使用注入的Mediator )
举例:武林门盟主,可以推送消息;具体中介者,(容纳了各个具体门派,用来处理逻辑);门派抽象类,具体门派类
观察者模式(Subject、ConcreteSubject、Observer、ConcreteObserver)
对象与对象之间的依赖关系,广播通信
Subject: (抽象类,目标,1.包含List<Observer>,2. 定义观察方法,用于改变观察者Observer的状态)
ConcreteSubject: (具体目标,1.实现 Subject 的方法,实际操作Observer)
Observer: (接口,观察者, 1.定义了 抽象类的改变规则)
ConcreteObserver: (具体观察者, 1.实现了 Observer ,具体改变规则方案)
状态模式(Context、State、ConcreteState)
一个对象在其内部状态改变时改变它的行为
Context:(环境类,1. 参入引入 State,2. 按照入参不同,模拟环境不同,返回不同具体状态 ConcreteState )
State:(接口,抽象状态类,定义了对象的状态规则)
ConcreteState:(具体状态类,1.实现了State,针对各个对象的状态行为)
策略模式(Context、Strategy、ConcreteStrategy)
一系列算法,将每一个算法封装起来,并让它们可以相互替换;客户端必须知道所有的策略类
Context: (普通类,环境类,1.注入策略类 Strategy 作参数 2. 构造函数注入 Stratege 3.具体实现方法,引用 Strategy 的方法)
Strategy: (接口,抽象策略类,指定算法类型,例:排序算法)
ConcreteStrategy: (普通Class,具体策略类,1. 实现Strategy,2. 例:冒泡排序、快速排序、堆排序……)