03设计模式
2021-10-30 12:03:24 22 举报
AI智能生成
设计模式
作者其他创作
大纲/内容
结构型模式
04Facade门面模式
1、Facade门面模式:坦克大战
1)解决添加游戏物体的问题
2)Frame只做展示、新增GameModel来进行内部逻辑计算、所有的游戏物体继承GameObject
2、经典应用:对外接口
1)为子系统中的一组接口提供一个一致的界面,定义了一个高层接口
2)个人项目经验:对外仅提供一个接口,然后指定调用接口时需要传入的参数、加密规则。系统根据接口来调用系统内子模块功能。
05Mediator调停者/中介模式
1、可参考:https://www.jianshu.com/p/4b57ed461a54
2、Mediator调停者:专门协调内部各角色的,鼎鼎大名的应用是“消息中间件”
08Composite组合模式
1、树状结构专用模式
2、父类Node,子类有LeafNode叶子节点和BranchNode分支节点
09Flyweight享元模式
1、重复利用对象:共享元数据,比如word当中,在一个FlyweigthPool中放了A...1...啊...等元对象,要使用的时候拿出来;
围棋
2、池化的思想:String、数据库连接池
3、内部状态和外部状态
内部状态:是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享。【比如围棋的颜色】
外部状态:是随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。【比如围棋的位置】
10Proxy静态代理与动态代理
1、引入:记录坦克的运行时间
1)Movable接口,move方法;
2)Tank实现Movable,前后取系统时间?
2、TankTimePorxy代理类
1)实现同一个Movable接口、聚合Tank
2)move里面调用tank的move方法,前后获取系统时间
3、TankLogProxy代理类,实现Movable接口
4、静态代理
1)Proxy代理类和被代理类都实现同一个接口Movable
2)代理类聚合接口,实现代理类实现嵌套
5、**LogProxy不仅可以代理Movable接口,也可以代理其他接口,如何实现?---使用java的代理类Proxy
6、Proxy.getProxyInstance(ClassLoador,Class[],InvocationHandler)
1)asm操作二进制文件
2)去看Proxy源码
3)需要实现接口
7、instrment琴弦?
8、CGLIB实现动态代理不需要接口【maven库】
1)Enhancer接口,生成的代理类是被代理类的子类
2)不能代理Final类型的类
9、Spring的AOP
14Adapter适配器(转换器)
1、接口转换器(电压转换器、转接口、java.io)
2、InputStreamReader就是一个适配器;
JDBC-ODBC-Bridge
3、常见的Adapter结尾的不是Adapter模式:
windowsAdapter(接口方法太多,抽象类重写空方法)
05Decorator装饰器模式
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
参考:https://www.jianshu.com/p/8cadee8b88e1
Java的IO
spring cache 中的装饰者模式
TransactionAwareCacheDecorator
spring session 中的装饰者模式
Mybatis 缓存中的装饰者模式
说明
Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
15Bridge桥接
1、双维度扩展:两个不同维度的东西桥接起来
分离抽象与具体、使用聚合方式连接抽象与具体
2、引入:帅哥送礼物,礼物的种类【书、花】、类型【温馨的、狂野的、有趣的】。如果使用继承,会导致类爆炸增长
3、桥接模式:
1)WarmGift继承Gift
2)Flower继承GiftImpl
3)Gift聚合GiftImpl
4)Gift g=new WarmGift(new Flower);
行为型模式
02策略模式Strategy
1、Comparable、Comparator
1.1、类图
2、比较数组大小,进行排序
1)比较一个int型数组开始
2)如何比较一个Cat类型的数组?Cat内部定义比较大小的方法compareTo(Cat b)
3)需要排序的对象,实现Comparable接口,并指定java类型,重写compateTo方法【方法里面指定使用某个属性进行对比】。那Sorter类就可根据对象的compateTo方法进行比较大小。---弊端:当我需要改变对比的属性时,就需要修改java类型中的compateTo方法
4)针对3)的改进:调用Sorter类的sort方法时,传入一个comparator类对象,然后sort方法内调用comparator中的compare方法进行排序----这样要改变对象的属性时,只需要替换comparator实例即可。
3、理论总结
1)每次当我们需要改变排序方式的时候,Sorter类是不用修改的,只要新增一个Comparator接口【策略接口】的实现类,并将实例【策略实例】传给Sorter类的sort方法。
4、策略模式的实际使用
1)坦克大战项目中tank的fire方法:比如策略1打一颗子弹、策略2打4颗子弹...
5、支付接口:https://blog.csdn.net/youanyyou/article/details/116931663
06ChainOfResponsibility责任链模式
1、论坛中过滤敏感词、过滤注入代码的过滤器责任链
1)Filter接口
2)FilterChain类包含add(Filter)、doFilter
3)让第2)的add返回filterChain对象本身,则可以实现.add().add()...
4)让第2)步的FilterChain实现Filter接口,则可以实现filterChain.add(filterChain2)
5)第4)中多个责任链执行时,每个fc执行过程中可以决定是否执行下一个fc对象:让Filter接口的doFilter返回boolean值
2、同一组FilterChain过滤request和response,要求request过滤顺序是fc1、fc2、fc3,response的过滤顺序是fc3、fc2、fc1.
关键代码:
1)普通filter
doFilter(request,response,filterChain){
request处理
filterChain.doFilter
response处理
}
2)FilterChain
Java的Filter类
07Observer观察者模式
我愿称之为“观察团模式”,源对象通知观察团,观察团根据事件做出反应
1)被监听(事件源对象):将监听者放在list中,事件发生时循环调用list中监听者的actionHappen方法
2)事件类:Event,存放事件相关信息,及源对象(被监听者)
3)监听者:监听者接口Observer接口有方法actionHappen(Event event);由监听者实现Observer接口,并根据event做出响应;
实际:监听小孩哭:时间、地点...观察者做出反应;
监听按钮事件;
observer、listener、hook、coallback全是观察者模式
11Iterator迭代器
1、遍历专用模式
2、物理存储结构只有两种
1)连续存储:数组
2)不连续存储:链表,指针指向下一个存储地址
3)数组和链表的实现
3、如何遍历容器--迭代器模式Iterator
1)只有容器知道自己的结构,由容器自己实现遍历
2)hashNext(),next()
12Visitor访问者
1、在结构不变的情况下动态改变对于内部元素的动作
2、电脑门店接待访客【电脑组件结构固定】
1)Vistor实现类自己实现报价策略
2)电脑组件分别接待accept(Vistor v),调用Vistor实现类的方法实现报价
3、这个模式实际中应用比较少,主要应用在编译器上面
16Command命令
1、封装命令:结合cor责任链实现undo
2、do和undo
18Memento备忘录
1、作用:记录状态便于回滚
2、记录快照、存盘:tank项目的保存和下载
1)ObjectOutStream、ObjectInStream
19TemplateMethod模板方法
1、钩子函数
1)父类中有模板方法、op1、 op2方法,模板方法中调用op1和op2;
2)子类只要重写op1、op2那么调用模板方法就能调用子类的op1、 op2
20State状态
1、根据状态决定行为【适合行为种类比较固定的】
2、Client类:根据状态来执行操作的,那干脆把状态抽象成一个抽象类里面有handle方法,然后子类实现handle方法
1)State state;
2)operate()->state.handle();【operate比较固定的时候】
3、拓展:有限状态机;多线程中线程的状态
21Intepreter解释器
1、动态解析脚本
指导思想
可维护性Maintainability:修改功能,需要修改的地方越少,可维护性越好
可复用性Reusability:代码可以重复利用
可拓展性Extensibility/Scalability:添加功能无需修改原来代码
灵活性flexibility/mobility/adaptability:代码接口可以灵活调用
六大原则
单一职责Single Responsibility Principle:一个类负责单一职责、高内聚、低耦合
开闭原则Open-Closed Principle:对拓展开发、对修改关闭;抽象话、多态是关键
里氏替换原则Liscov Substitution Principle:所有使用父类的地方都能够透明的使用子类对象
依赖倒置原则Dependency Inversion Principle:依赖抽象不依赖具体
接口隔离Interface Segregation Principle:每个接口承担独立角色,避免子类实现不需要的方法
迪米特原则Law Of Demeter Principle:不要和陌生人说话
1)当前对象本身this
2)当前对象的方法中的参数对象
3)当前对象的成员对象
4)当前对象的集合类型的成员对象中的元素
5)当前对象所创建的对象
创建型模式
01单例模式Singleton
1、只需要一个实例
2、比如各种Manager类、各种Factory类;
Spring中的ApplicationContext、数据库连接池
3、饿汉式:类加载到内存后,就实例化一个单利,JVM保证线程安全(简单实用,推荐使用)
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
分支主题
4、懒汉式:调用静态getInstance方法的时候,判断是否存在实例,如果没有则创建(按需初始化、会有多线程问题)
5、懒汉式加锁1:给静态方法getInstance加锁(无多线程问题、效率降低)
6、懒汉式加锁2:静态方法getInstance不加锁,给创建实例的代码加锁(多线程问题、效率降低)
7、懒汉式加锁3:静态方法getInstance不加锁,给创建实例的代码加锁,双重判断是否未null(感觉像套娃。。。)
8、静态内部类方式:
1)JVM保证单例(每个类只加载一次,所以内部静态类也只加载一次)
2)通过内部静态类创建外部类实例
3)getInstance中通过内部静态类返回实例
4)加载外部类的时候不会加载内部类,实现了懒加载
9、枚举单例:解决线程问题、同时防止反序列化(因为没有构造方法,不会被反序列化)
03工厂模式
1、简单工厂:
1)任意定制出行工具,工厂类SimpleFactory根据传入的类型创建不同的出行工具,如汽车、飞机、火箭
2)
2、工厂方法:产品维度扩展
1)工厂接口,由子类实现接口方法,每个子类只创建一种产品
2)
3、抽象工厂:产品一族扩展
1)工厂接口中,可以创建一个产品族的多个产品,由子类实现接口方法
2)个人理解:抽象工厂≈简单工厂+工厂方法
4、备注:
1)形容词用接口、名称用抽象类。比如moveable接口、food类
2)坦克大战中使用抽象工厂实现坦克的不同皮肤套装(坦克颜色、子弹颜色、爆炸颜色)
5、springIOC、bean工厂
1)https://www.cnblogs.com/tanshaoshenghao/p/10770659.html
2)模拟ISpring的Bean工厂
public ClassPathXmlApplicationContext(String propAddr) throws Exception {
SAXReader reader = new SAXReader();
File file = new File(this.getClass().getClassLoader().getResource(propAddr).toURI());
Document document = reader.read(file);
Element root = document.getRootElement();
List<Element> childElements = root.elements();
for (Element child : childElements) {
Object bean = Class.forName(child.attributeValue("class")).newInstance();
container.put(child.attributeValue("id"), bean);
}
}
13Builder构建器
1、用来构建复杂对象:https://www.jianshu.com/p/afe090b2e19c
1)要建造的产品Product -- 组装的电脑
2)抽象的Builder -- 装CPU、内存条、硬盘等抽象的步骤
3)Builder的具体实现ConcreteBuilder -- 对上述抽象步骤的实现,比如装i5CPU、8G内存条、1T硬盘【聚合Product】
4)使用者Director -- 电脑装机人员
2、典型应用:
1)比如创建一个账号,需要很多信息,但是不是每个账号
需要的信息都是一样的。有些需要基本信息、有些需要住址信息、有些需要工作信息。那么这个时候可以有个PersonBuilder,通过这个类去把各种信息分步创建。
Person p =new Person.PersonBuilder()
.basicInfo(var1,var2,var3,var4)
.score(var1,var2)
.location(...)
.work(...);
17Prototype原型
1、Object.clone()
2、标记性接口:Cloneable,要重写clone方法的类必须实现Cloneable接口
3、浅克隆:引用类型的属性,不实现Cloneable接口
深克隆:引用类型的属性也实现Cloneable接口,在克隆对象的时候引用类型的属性也同时需要克隆。
4、String类型的属性,如果不是用new的,不需要深克隆
1)个人理解:因为不是new的,那改变String类型值的时候,是在常量池新增一个常量,然后指向这个对象。而克隆出来的属性还是指向原来的常量。
加号(+)表示具有公共可见性(public)
减号(-)表示私有可见性(private)
#号表示受保护的可见性(protected)
省略这些修饰符表示具有package(包)级别的可见性
属性或操作具有下划线,表明它是静态的
在操作中,可同时列出它接受的参数,以及返回类型
0 条评论
下一页