观察者模式,策略模式,适配器模式
观察者模式
1.1、观察者模式概述
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系(注册),使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新(通知)。说白了就是个注册,通知的过程。
观察者模式的主要角色
抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种。
抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
1.2、观察者模式的优缺点
观察者模式是一种对象行为型模式,其主要优点如下:
降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
目标与观察者之间建立了一套触发机制。
它的主要缺点如下:
目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
1.3、观察者模式注意事项
1、JAVA 中已经有了对观察者模式的支持类。
2、避免循环引用。
3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。
1.4、异步处理线程安全问题
被观察者发生动作了,观察者要做出回应,如果观察者比较多,而且处理时间比较长怎么办?那就用异步呗,异步处理就要考虑线程安全和队列的问题,这个大家有时间看看 Message Queue,就会有更深的了解。
class Producer {private List<IConsumer> consumerList = new ArrayList<>();public void add(IConsumer consumer) {consumerList.add(consumer);}public void notifyObserver(String message){for (IConsumer obs:consumerList){obs.response(message);}}
}class CurrentProducer extends Producer {public void send(String message) {System.out.println("发送消息:"+message);super.notifyObserver(message);}
}interface IConsumer {void response(String message);
}class Consumer implements IConsumer {@Overridepublic void response(String message) {System.out.println("消费者1接收消息:"+message);}
}class Consumer2 implements IConsumer {@Overridepublic void response(String message) {System.out.println("消费者2接收消息:"+message);}
}public class Test1 {public static void main(String[] args) {CurrentProducer producer = new CurrentProducer();IConsumer consumer = new Consumer();IConsumer consumer2 = new Consumer2();producer.add(consumer);producer.add(consumer2);producer.send(UUID.randomUUID().toString());}
}
输出结果
发送消息:89f997f6-4688-4950-9d3f-5d86615098fd
消费者1接收消息:89f997f6-4688-4950-9d3f-5d86615098fd
消费者2接收消息:89f997f6-4688-4950-9d3f-5d86615098fd
策略模式
1.策略模式简介
策略模式:策略模式是一种行为型模式,它将对象和行为分开,将行为定义为 一个行为接口 和 具体行为的实现。策略模式最大的特点是行为的变化,行为之间可以相互替换。每个if判断都可以理解为就是一个策略。本模式使得算法可独立于使用它的用户而变化
2.模式结构
策略模式包含如下角色:
Strategy: 抽象策略类:策略是一个接口
Context: 环境类 /上下文类
ConcreteStrategy: 具体策略类
案例
电商购物车系统价格计算:
1.普通会员没有优惠
2.中级会员打9折
3.高级会员打8折
1).传统实现方式
public Double calculationPrice(String type, Double originalPrice, int n) {//中级会员计费if (type.equals("intermediateMember")) {return originalPrice * n * 0.9;}//高级会员计费if (type.equals("advancePrimaryMember")) {return originalPrice * n * 0.8;}//普通会员计费return originalPrice;}
2).策略模式实现
抽象类策略
interface MemberStrategy {// 一个计算价格的抽象方法//price商品的价格 n商品的个数double calcPrice(double price, int n);
}
具体实现类
// 普通会员——不打折
class PrimaryMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double price, int n) {return price * n;}
}// 中级会员 9折
class IntermediateMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double price, int n) {return price * n * 0.9;}
}// 高级会员 8折
class AdvanceMemberStrategy implements MemberStrategy {@Overridepublic double calcPrice(double price, int n) {return price * n * 0.8;}
}
上下文类或环境类,起承上启下封装作用
class MemberContext {private MemberStrategy memberStrategy;public MemberContext(MemberStrategy memberStrategy) {this.memberStrategy = memberStrategy;}//计算价格public double qoutePrice(double goodsPrice, int n) {// 通过接口变量调用对应的具体策略return memberStrategy.calcPrice(goodsPrice, n);}}
测试类
public class test1 {public static void main(String[] args) {//普通会员价格计算PrimaryMemberStrategy primaryMemberStrategy = new PrimaryMemberStrategy();MemberContext memberContext = new MemberContext(primaryMemberStrategy);//中级会员价格计算IntermediateMemberStrategy intermediateMemberStrategy = new IntermediateMemberStrategy();MemberContext memberContext2 = new MemberContext(intermediateMemberStrategy);//高级会员价格计算AdvanceMemberStrategy advanceMemberStrategy = new AdvanceMemberStrategy();MemberContext memberContext3 = new MemberContext(advanceMemberStrategy);//计算一本100块钱的书System.out.println("普通会员的价格:"+ memberContext.qoutePrice(100,1));// 普通会员:100System.out.println("中级会员的价格:"+ memberContext2.qoutePrice(100,1));// 中级会员 90System.out.println("高级会员的价格:"+ memberContext3.qoutePrice(100,1));// 高级会员80}
}
输出结果
普通会员的价格:100.0
中级会员的价格:90.0
高级会员的价格:80.0
4.策略模式优缺点
1)优点
策略模式提供了对“开闭原则”的完美支持,用户可以在不 修改原有系统的基础上选择算法或行为,也可以灵活地增加 新的算法或行为。
策略模式提供了管理相关的算法族的办法。
策略模式提供了可以替换继承关系的办法。
使用策略模式可以避免使用多重条件转移语句。
2)缺点
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
策略模式将造成产生很多策略类,可以通过使用享元模式在一 定程度上减少对象的数量。
5.策略模式适用场景
在以下情况下可以使用策略模式:
如果在一个系统里面有许多类,它们之间的区别仅在于它们 的行为,那么使用策略模式可以动态地让一个对象在许多行 为中选择一种行为。
一个系统需要动态地在几种算法中选择一种。
如果一个对象有很多的行为,如果不用恰当的模式,这些行 为就只好使用多重的条件选择语句来实现。
不希望客户端知道复杂的、与算法相关的数据结构,在具体 策略类中封装算法和相关的数据结构,提高算法的保密性与 安全性。
在我们生活中比较常见的应用模式有:
1、电商网站支付方式,一般分为银联、微信、支付宝,可以采用策略模式
2、电商网站活动方式,一般分为满减送、限时折扣、包邮活动,拼团等可以采用策略模式
适配器模式
1.什么是适配器模式?
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作
2.适配器模式中的角色分析
目标接口(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。
需要适配的类(Adaptee):需要适配的类或适配者类。
适配器(Adapter):通过包装一个需要适配的对象,把原接口转换成目标接口。
3.实现方式
1).类适配器(采用继承实现)
2).对象适配器(采用对象组合方式实现)
4.类适配器:
因为 Adapter 类既继承了 Adaptee (被适配类),也实现了 Target 接口(因为 Java 不支持多继承,所以这样来实现)所以被称为类适配器
实例(以插网线上网举例):
1)首先我们拥有一根网线,他有上网的功能,但是它的接口与电脑不匹配
//要适配的类:网线
public class Adaptee {//功能:上网public void request(){System.out.println("链接网线上网");}
}
2)因此我们定义了一个usb接口,也就是上面提到的目标接口(Target)
//接口转换器的抽象实现
public interface NetToUsb {//作用:处理请求,网线=>usbpublic void handleRequest();
}
3)定义一个适配器继承着网线,连接着usb接口
public class Adapter extends Adaptee implements NetToUsb {
@Overridepublic void handleRequest() {super.request();//可以上网了}
}
对象适配器的优点:
一个对象适配器可以把多个不同的适配者适配到同一个目标
可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据’里氏替换原则’适配者的子类也可以通过该适配器进行适配
类适配器的缺点 :
对于java,c#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不同同时适配多个适配者
在java,c#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性
使用场景:
系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码
观察者模式,策略模式,适配器模式相关推荐
- 设计模式1——策略模式 | 适配器模式 | 工厂模式
最近在看<Think In JAVA>,其中在讲解继承,组合,抽象类和接口的时候,提到了题中的几个设计模式.这几个设计模式也确实让我更好的理解了JAVA中各个数据结构的含义.今天就结合书本 ...
- 图解Java设计模式学习笔记——行为型模式(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式)
一.模板方法模式(模板模式)--钩子方法 1.需求-豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材-->添加配料-->浸泡-->放到豆浆机打碎. 通过添加不同的配料 ...
- 设计模式-策略模式,观察者模式,装饰者模式,静态工厂模式,工厂方法模式
设计模式这个东西,永远不是单单从书本上就能获取到的东西.曾经看到一个比喻,比喻的就很巧妙,文艺复兴时期的教学方式,那时候诞生了很多巨匠,达芬奇,莫开朗基罗,拉斐尔都是在这个时期绽放光芒的巨星.有一种说 ...
- 策略模式、观察者模式、代理模式、装饰模式 应用场景和实现
有个大神写的很好: 参考:设计模式学习笔记(四:策略模式) 参考:设计模式学习笔记(二:观察者模式) 参考:设计模式学习笔记-代理模式 参考:设计模式--装饰者模式与代理模式(重要) 参考:设计模式- ...
- 策略模式、观察者模式、状态模式原理及实例
策略模式 基本介绍 策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 这算法体现了几个设计原则. 第一 把变化的 ...
- 设计模式:策略模式+观察者模式
以游戏情景举例: 情景:一个boss发动一个技能时会让自己的喽啰收到随机的增益效果. 提取一下主要需求: 1:随机增益效果 2:通知多个对象 其中1用策略模式+工厂模式来解决,2用观察者模式来解决 先 ...
- Java设计模式系列3-----装饰模式,策略模式,观察者模式
1.装饰模式 装饰(Decorator)模式又叫做包装模式.通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一个替换方案. package com.ibeifeng.news;public i ...
- 设计模式之策略模式、观察者模式浅析
head first 设计模式 这本书上学的时候就买了,一直没看,最近下班后实在是不想对着电脑,就翻了翻以前没看的书,看到<head first 设计模式>后,发现这本书写的真不错啊 强烈 ...
- 设计模式(一):模板方法、观察者模式、策略模式
文章目录 1. 了解设计模式 2. 如何学习设计模式 3. 设计原则 3.1 依赖倒置原则 3.2 开放密闭原则 3.3 面向接口原则 3.4 封装变化点原则 3.5 单一职责原则 3.6 里氏替换原 ...
最新文章
- MySQL InnoDB锁机制全面解析分享
- 安卓突击:Android 动画有哪几种?
- C#实现RSA加密解密
- Ubuntu中vi / vim编辑器快捷操作
- ARC106——E - Medals
- jQuery BreakingNews 间歇滚动
- linux的基础知识——会话
- qq互动视频页面加载失败_互动案例技术分析(2)
- php preg_match正则匹配中文-有深意
- access denied (java.io.FilePermission IKAnalyzer.cfg.xml read
- EasyUI 二级联动
- WINDOWS系统最近使用的项目路径
- 机器学习之决策树(数据分析师学习必备)——糖潮丽子的博客
- 利用masm32输出PE文件头的基本属性
- centos 卸载apache
- linux 通过关键字查询到进程,并kill掉
- webrtc音频QOS方法三(回声的产生及抑制)
- 2022机器学习好网站大收藏
- 可解释的人工智能 = 三维结构芯片 + 仿突触运动
- 浅谈stm32的低功耗模式