目录
首先,感谢LoveLion 这位博主,我的设计模式是跟着这位大佬学的,大佬讲解的很好,通俗易懂。史上最全设计模式导学目录(完整版)https://blog.csdn.net/LoveLion/article/details/17517213
这是文章的链接。
————————————————————————————
Java实现设计模式https://gitcode.net/qq_45851715/designpatterns 这是设计模式的实现相对应的实现
——————————面向对象设计原则——————————
—————————————感悟————————————
下面是我学习设计模式的感悟,以及对设计模式的理解。
六个创建型模式
简单工厂模式
最简单的工厂模式,将原本在主类中创建的具体的产品挪到了工厂里,由一个工厂去负责创建具体的类,在主类中只需要声明一个抽象的产品类,然后调用工厂的方法即可。类似于一个生产桌子的代工厂,它既可以生产A家的,也可以生产B家的。
工厂方法模式
简单工厂的升级版,原来的产品类不发生变化,依旧是一个抽象的产品,例如桌子,然后下有具体的产品,例如A家桌子,B家桌子。
但工厂类发生了变化,抽取出一个抽象的工厂类,随后,有几个不同的具体的工厂子类,例如,他们都是生产桌子工厂,但工厂还可以分为A工厂,B工厂。A工厂生产A桌子,B工厂生产B桌子。
就是A公司和B公司他们两家支楞起来了,以前没钱,只能用代工厂,现在有了点资本,可以自己有自己的工厂了
抽象工厂模式
依旧是之前的A公司和B公司,他们现在有了自己工厂,随着资本的积累(万恶的资本主义) ,他们的工厂现在不仅可以生产桌子,还可以生产椅子。
到真实的代码里的表现为,一个抽象的工厂类,随后有具体工厂A,具体工厂B。工厂A中有创建A桌子,A椅子的方法。工厂B中有创建B桌子,B椅子的方法。
单例模式
饿汉式,
定义一个类,直接在类中用
private static final eagerSingleton eager = new eagerSingleton();
把类的对象创建出来,然后提供Get方法让主类调用。
懒汉式
定义一个类,在get方法中完成该类对象的创建,(如果没有就创建一个,有就直接调用)
package creativemode.singletonpattern;
/**
* 懒汉式,调用之前,先检查有没有,没有在创建
*/
public class LazySingleton {
private static LazySingleton lazySingleton=null;
public static LazySingleton getLazySingleton() {
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
return lazySingleton;
}
}
class dome2{
public static void main(String[] args) {
LazySingleton lazy1,lazy2;
lazy1= LazySingleton.getLazySingleton();
lazy2= LazySingleton.getLazySingleton();
System.out.println(lazy1==lazy2);
}
}
原型模式
又称克隆模式主要为了克隆。克隆又分为深克隆(用流的方式写到文件,什么都可以写,功能强大)和浅克隆(把A克隆给B, 在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,)。
浅克隆
建造者模式
就像是抽象工厂模式,然后又加了一个管理者类,要一次调用,创建具体工厂中的所有对象
七个结构型模式
适配器模式
感觉就是在一个方法中调用另一个方法,类似于偷梁换柱,你看到一个猫, 让他叫一声,听到的是一声狗叫,他就是一个披着猫皮的狗。
桥接模式
参照毛笔结构示意图,桥接模式的效果类似于农村包围城市,由两个实现类(准确的说应该是一个具体实现类,一个接口<不过接口后面也要跟实现类的嘛>)对方法形成两面包加芝士。 调用时,由毛笔进行调用 桥不是关键
组合模式
组合模式:组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式
把它放到一个数组里,去递归的调用,因为leaf和composite是一样的,所以递归时,没有障碍
@Override
public void open() {
System.out.println("打开文件夹 "+name);
for(Object obj:filelist){
((component)obj).open();
}
}
装饰模式 代理模式
功能增强,将ConcerteComponent对象作为参数传递给ConcerteDecorator调用其operation方法来对ConcerteComponent进行增强。 但对主类来说,他们都是Component
与代理模式(代购)有一点点相似,不过,装饰模式要先造出一个原型,然后对原型进行增强,原型的方法和增强后的方法,方法名一致,主类无需关心变化问题(增强后,我依旧是我,没有变)。
代理模式不用造出原型,毕竟人家干的就是代理,在主类中创建一个代理类的对象,调用代理类的方法,代理类的方法中包含了原型的方法,同时,代理类可以夹带一点私货,写一些别的东西(这其实也可以理解为一种增强了),不过他的灵活性比起装饰模式稍差一点
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
代理模式是一种对象结构型模式。在代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。
外观模式
和抽象工厂类、对象适配器类有异曲同工之妙,差异在于:外观模式注重多个子系统组件的统一(哈哈,这么说也没错,不过我之前说的是灵活性不过),提供一个方便的接口;抽象工厂是返回一些具有共性的产品;而对象适配器则注重不同接口之间的兼容
package structuralpattern.facadepattern;
public class facade {
private subsystemA subA=new subsystemA();
private subsystemB subB=new subsystemB();
private subsystemC subC=new subsystemC();
/**
* 灵活性差点意思
*
* 从缺省适配器模式那里的到的灵感,做一个空方法,如果需要再重写,
* 但,太麻烦了,且要多设计好几个类,
*/
public void method(){
subA.methodA();
subB.methodB();
subC.methodC();
}
}
享元模式
享元模式的核心理念是共享,有个享元模式,这里面放着对象,用的时候直接拿,例如围棋,五子棋这种分为黑棋、白棋,每一个棋子的位置都不一样,要是每一个都创建一个对象,那就很容易玩蹦的,内存就那么点。
我们可以想个办法,不看位置,黑棋、白棋其实只用创建两个对象。然后记录的时候,拿一个白棋对象然后记录位置就行了,能省不少内存空间。
说白了就是把公共的部分提取出来,以单例的形式表示。内部状态是持久态,因此我们需要使用享元池将这个持有内部状态的享元对象保存起来。外部状态一般是瞬时态,用完即弃。
享元模式结构较为复杂,一般结合工厂模式一起使用,在它的结构图中包含了一个享元工厂类
享元模式结构图
引入外部状态之后的围棋棋子结构图
十一个行为型模式
职责链模式
职责链模式并不创建职责链,职责链的创建工作必须由系统的其他部分来完成,一般是在使用该职责链的客户端中创建职责链
与策略模式有一点点相似,不同的是职责链构建起来后,只调用指责链的头就可以了
同样是一个抽象的职责类,然后下面在细分出不同的具体的指责类,来实现抽象类中的抽象方法。还有一个请求类,请求类作为参数传入到抽象方法中。
注意,若该请求在职责链的最后也没有执行成功,会报错。建议在最后一个类中修改方法,或者在最后一个指责后再添加一个指责,用来解决该问题
命令模式
命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求
命令模式(Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
一个请求者类,请求者类中包含着对抽象命令类的引用,请求者类调用请求方法时,抽象命令类是他的形参。具体的命令类完成对抽象命令类的实现。
就整体架构而言,与简单工厂模式是很相似的,只是解决问题的角度不太一样
解释器模式
这个没怎么搞懂,就直接上概念吧
解释器模式(Interpreter Pattern):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。 解释器模式的结构与组合模式的结构有些类似,但在解释器模式中包含更多的组成元素
迭代器模式
将聚合类中负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历分离,无须暴露聚合类的内部属性即可对其进行操作
java中集合都有迭代器这个类。可以直接调用
在具体聚合类的创建迭代器方法中,返回值为,将自身作为参数传入迭代器,并返回
@Override
public abstractIterator createIterator() {
return new iterator(this);
}
中介者模式
* 如果在一个系统中对象之间存在多对多的相互关系,我们可以将对象之间的一些交互行为从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行统一协调,这样对象之间多对多的复杂关系就转化为相对简单的一对多关系。 * 中介者模式(Mediator Pattern):用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。 * 有一点点像观察者模式 或者说,星形网络
引入中介者对象的星型结构
在抽象中介者类中,添加一个抽象同事类的数组集合,用于将具体的同事类添加到集合中。
备忘录模式
* 备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。它是一种对象行为型模式,其别名为Token。
这个简单,简单来说就是,在一个真实类,一个备忘录类,备忘录类中的属性,一般与真实类保持一直,在真实类中具有保存方法和撤销方法,保存方法就是将真实类中的数据给备忘录类复制一份。撤销方法就是将备忘录类中的数据,还给真实类。
这个时候,大部分问题已经解决了,但是你会发现,我们只可以撤销一次,为了实现多步的撤销,再搞一个负责人类,其中有备忘录类类型的数组集合。将保存的备忘录类放到数组里,从而实现多不撤销。
那么代价是什么呢? 代价是浪费资源,每保存一次,都要往数组里放一个,生产队的驴都不敢这么使,所以一般会在加一个撤销上限。
观察者模式
观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
观察者模式分为两大类,一类是观察目标(下面简称目标),一类是观察者。(一个抽象目标类,有具体的目标类,观察者一样)
用红绿灯举例子。车子到达了某个路口,(抽象目标类中有一个抽象观察者类型的数组 ,来一个,加一个),当发现路口是红灯,于是车子们都停车了(具体目标类实现抽象方法,执行该方法,该方法内部便利那个抽象观察者类型的数组,调用观察者的方法)
状态模式
* 状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
与职责链模式极为相似,只是角度发生了一点点不一样。
在状态模式中一个抽象的类,它可能因为一些变化,会变得不太一样,将会变化的方法设为抽象方法,交由子类去实现。 再来一个环境类保持对抽象类的引用,在环境类中描写,在什么情况下状态会不一样,从而创建不同的子类。
策略模式
* 策略模式的主要目的是将算法的定义与使用分开,也就是将算法的行为和环境分开 * 策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。
针对一个问题,给出不同的解决方法,熟悉吗,是不是很眼熟,和职责链模式,状态模式有点相似。
模板方法模式
这个没啥说的,说白了就是一个基于继承的代码复用技术
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
访问者模式
访问者模式(Visitor Pattern):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。 元素组为主,访问者为次,在元素组中调用了访问者中的方法,从而实现对数据的计算