Reference
设计模式串联
创建型
单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
有个人自己开了一家餐厅,这家餐厅只有一个老板。
|
|
饿汉式
|
|
懒汉式(线程不安全)
|
|
懒汉式(线程安全)
|
|
懒汉式(双重校验锁,线程不一定安全)
|
|
懒汉式(双重校验锁,线程安全)
|
|
枚举
|
|
静态内部类
|
|
建造者模式(Builder)
将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
老板打算在招聘网站上招人,一般就是填写完招人要求后,网站返回符合要求的人。
|
|
- 测试123456789101112public class Test {public static void main(String[] args) {招人 服务员 = new 招人.招人要求(辅助点餐).set年龄(60以下).set性别(男女均可).开始查找();招人 厨师 = new 招人.招人要求(做菜).set年龄(60以下).set性别(男女均可).开始查找();}}
工厂方法模式(FactoryMethod)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
老板可能从某联上招人,也可能从某勾上招人,某联使用的就是某联的数据库,某勾使用的是某勾的数据库。
|
|
- 测试12345public class Test {public static void main(String[] args) {new 某勾招聘网站().招聘();}}
抽象工厂模式(AbstractFactory)
为创建一组相关或者是相互依赖的对象提供一个接口,而不需要指定他们的具体实现类。
招聘网站千千万找不过来,老板决定让猎头找。
|
|
- 测试12345public class Test {public static void main(String[] args) {new 猎头招聘网站().招聘();}}
原型模式(Prototype)
创建对象的种类,并通过拷贝这些原型创建新的对象。
餐厅经营得不错,一段时间后,老板开了一家分店,又招了一批服务员和厨师,但是老板还是一个。
|
|
- 测试12345public class Test {public static void main(String[] args) {总店.clone().员工花名册();}}
结构型
适配器模式(Adapter)
将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。
老板在某聘上招人,因为某聘和某联合作,所以某聘直接使用某联的人才库。
|
|
- 测试12345public class Test {public static void main(String args[]) {new 某聘招聘网站().招聘();}}
装饰模式(Decorator)
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
当服务员请假时,厨师可以兼任服务员的工作。
|
|
- 测试1234567public class Test {public static void main(String args[]) {可以兼任工作的厨师 厨师 = new 可以兼任服务员的厨师(new 某联人才库中的厨师());厨师.做菜();厨师.额外工作();}}
代理模式(Proxy)
调用原有的方法,且对产生的结果进行控制。
由于洗菜工还未入职,所以厨师做菜前,需要先洗菜。
|
|
- 测试12345public class Test {public static void main(String args[]) {new 需要洗菜的厨师(new 某联人才库中的厨师()).做菜();}}
组合模式(Composite)
将对象组合成树形结构以表示“部分-整体”的层次结构。
建立管理层,且新店开业后归总店管理。
|
|
- 测试12345678910111213public class Test {public static void main(String args[]) {餐厅 总店 = 总店.getInstance();总店.add(new 客服部());总店.add(new 技术部());餐厅 分店 = new 餐厅();分店.add(new 客服部());分店.add(new 技术部());总店.add(分店);}}
桥接模式(Bridge)
把事物和其具体实现分开,使他们可以各自独立的变化。
老板想开发点餐软件,分为服务端和客户端,分别交给总店和分店的技术部实现。
|
|
- 测试1234567891011public class Test {public static void main(String[] args) {点餐软件专项组 总店的专项组 = new 总店的技术部();总店的专项组.set软件(new 服务端软件());总店的专项组.开始开发();点餐软件专项组 分店的专项组 = new 分店的技术部();分店的专项组.set软件(new 客户端软件());分店的专项组.开始开发();}}
外观模式(Facade)
避免几个类之间相互持有实例,将这几个类的实例放到同一个类中。
餐厅来了一个大客户,老板让一个大客户经理招待客户。
|
|
- 测试12345public class Test {public static void main(String[] args) {new 大客户经理().招待客户();}}
享元模式(Flyweight)
将大量的小的重复使用的对象统一管理起来,避免用户多次创建重复对象造成的资源浪费。
大客户又来了,老板会优先安排上次的大客户经理,但是如果上次的大客户经理正忙,就会重新安排大客户经理招待客户。
|
|
- 测试12345public class Test {public static void main(String[] args) {new 客服部().get大客户经理(大客户ID).招待客户();}}
行为型
观察者模式(Observer)
当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化。
老板进行面试,面试结束后通知参与面试的人面试结果。
|
|
- 测试12345678910111213public class Test {public static void main(String[] args) {面试官 一个面试官 = new 技术部面试官();面试者 一个面试者 = new 校招人员();一个面试官.add(一个面试者);一个面试官.add(new 校招人员());一个面试官.add(new 校招人员());一个面试官.add(new 社招人员());一个面试官.notify面试者(一个面试者);}}
访问者模式(Visitor)
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
客人排队就餐,叫到号后可以进店就餐。
|
|
- 测试12345678910public class Test {public static void main(String[] args) {服务员 一个服务员 = new 服务员(new 餐厅());一个服务员.添加排队的人(new 客户());一个服务员.添加排队的人(new 客户());一个服务员.添加排队的人(new 客户());一个服务员.开始叫号();}}
迭代器模式(Iterator)
老板助理按照员工花名册依次叫员工去老板办公室领工资。
|
|
- 测试12345678public class Test {public static void main(String[] args) {辅助老板发工资的人 老板助理 = new 老板助理(员工花名册);while(老板助理.看还有没有人没领工资()) {老板助理.叫员工去领工资();}}}
模板方法模式(TemplateMethod)
开发软件前先确定架构。
|
|
- 测试12345public class Test {public static void main(String[] args) {new 点餐软件().开始开发();}}
中介者模式(Mediator)
餐厅上线了外卖业务,订餐人向餐厅要一杯咖啡,餐厅委托骑手送咖啡。
|
|
- 测试123456789101112public class Test {public static void main(String[] args) {客户端 订餐者 = new 客户端();客户端 送餐者 = new 客户端();平台 外卖平台 = new 外卖业务(订餐者);外卖平台.set送餐者(送餐者);订餐者.发送消息("我要一杯咖啡");送餐者.发送消息("已取,马上为您送到");}}
备忘录模式(Memento)
主要目的是保存一个对象的某个状态,以便在适当的时候恢复对象。
老板规定分店每月保留10万用于平时开销,盈利部分划归总店,亏损部分总店补齐。
|
|
- 测试123456789101112public class Test {public static void main(String[] args) {餐厅 分店 = new 餐厅(100000);分店.买菜(1000);分店.卖菜(1500);分店.get资金();分店.月末结算();分店.get资金();}}
状态模式(State)
可以通过改变状态来获得不同的行为。
建立员工审批制度,员工先向直属上级发起审批请求,待审批通过后,再向店长发起审批请求。
|
|
- 测试12345678public class Test {public static void main(String[] args) {审批表 一个审批表 = new 审批表();while(一个审批表.get审批() != null) {一个审批表.走审批流程();}}}
策略模式(Strategy)
定义一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。
新店开业大酬宾,店长推出各种优惠活动:满200减50、老客户全单打9折、新客户全单打8折,优惠不能同时享。
|
|
- 测试12345678910public class Test {public static void main(String[] args) {账单 一个账单 = new 账单(100);float 不参加优惠活动的金额 = 一个账单.get帐单金额();float 参加满200减50的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new 满200减50(100)));float 参加老客户全单打9折的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new 老客户全单打9折(100)));float 参加新客户全单打8折的金额 = 一个账单.get帐单金额(一个账单.set优惠活动(new 新客户全单打8折(100)));float 最优惠金额 = sort(不参加优惠活动的金额, 参加老客户全单打9折的金额, 参加老客户全单打9折的金额, 参加新客户全单打8折的金额);}}
职责链模式(ChainOfResponsibility)
将接受请求的对象连成一条线链并且沿着这条链传递请求,直到有一个对象能够处理它为止。
有记者来采访,找到了保安,保安知道自己不能接受采访,把记者带给保安队长,保安队长也知道自己不能接受采访,把记者带给店长。
|
|
- 测试123456789101112public class Test {public static void main(String[] args) {餐厅职员 一个保安 = new 保安();餐厅职员 一个保安队长 = new 保安队长();餐厅职员 一个店长 = new 店长();一个保安.set上级管理者(一个保安队长);一个保安队长.set上级管理者(一个店长);一个保安.接受采访();}}
命令模式(Command)
命令模式的目的就是达到命令的发出者和执行者之间解耦,实现请求和执行分开。与责任链模式不同的是执行者是确定的,中途命令不能被处理,只能被传递。
又有记者来了,保安想起来上次是店长接受的采访,所以就知道了只要有记者来采访,就直接找店长。
|
|
- 测试12345678public class CommandTest {public static void main(String[] args) {店长 一个店长 = new 店长();公关预案 一个公关预案 = new 公关预案(一个店长);保安 一个保安 = new 保安(一个公关预案);一个保安.发现记者来了();}}
解释器模式(Interpreter)
在系统中如果某一特定类型的问题在频繁的发生,此时我们就有必要将这些问题的实例表述为一个语言中句子,因此可以构建一个解释器,然后利用该解释器来解释这些句子来解决这些问题。
两个记者分别来自不同的报社,一个是经济报社的,一个是美食报社的,虽然店长接受采访时和他们说了相同的内容,但是两个记者分别从两个角度完成了采访后稿件。
|
|
- 测试12345public class InterpreterTest {public static void main(String[] args) {new 美食报社记者().写采访后的稿件(店长接受采访时说的话);}}