对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。
@ Override
public void registerObserver (Observer observer ) {
observers .add (observer );
@ Override
public void removeObserver (Observer observer ) {
int index = observers .indexOf (observer );
if (index >= 0 ) {
observers .remove (index );
@ Override
public void notifyObservers () {
for (Observer observer : observers ) {
observer .update (msg );
* 主题更新信息
public
void setMsg (String msg ) {
this .msg = msg ;
notifyObservers ();
所有观察者需要实现此接口:Observer.java
public ObserverUser1 (Subject subject ) {
subject .registerObserver (this );
@ Override
public void update (String msg ) {
Log .e ("-----ObserverUser1 " , "得到 3D 号码:" + msg + ", 我要记下来。" );
最后测试:ObserverActivity.java
// 创建服务号
objectFor3D = new ObjectFor3D ();
// 创建两个订阅者
observerUser1 = new ObserverUser1 (objectFor3D );
observerUser2 = new ObserverUser2 (objectFor3D );
// 两个观察者,发送两条信息
objectFor3D .setMsg ("201610121 的3D号为:127" );
objectFor3D .setMsg ("20161022 的3D号为:000" );
2. 工厂模式
简单列一下这个模式的家族:
1、静态工厂模式
这个最常见了,项目中的辅助类,TextUtil.isEmpty等,类+静态方法。
2、简单工厂模式(店里买肉夹馍)
定义:通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
根据类型直接创建肉夹馍:SimpleRoujiaMoFactory.java
public RoujiaMo creatRoujiaMo (String type ) {
RoujiaMo roujiaMo = null ;
switch (type ) {
case "Suan" :
roujiaMo = new ZSuanRoujiaMo ();
break ;
case "La" :
roujiaMo = new ZLaRoujiaMo ();
break ;
case "Tian" :
roujiaMo = new ZTianRoujiaMo ();
break ;
default :// 默认为酸肉夹馍
roujiaMo = new ZSuanRoujiaMo ();
break ;
return roujiaMo ;
3、工厂方法模式(开分店)
定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。
对比定义:
1、定义了创建对象的一个接口:public abstract RouJiaMo sellRoujiaMo(String type);
2、由子类决定实例化的类,可以看到我们的馍是子类生成的。
提供创建肉夹馍店抽象方法:RoujiaMoStore.java
public abstract RoujiaMo sellRoujiaMo (String type );
具体实现抽象方法:XianRoujiaMoStore.java
分店依旧使用简单工厂模式:XianSimpleRoujiaMoFactory.java
4、抽象工厂模式(使用官方提供的原料)
定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。
对比定义:
1、提供一个接口:public interface RouJiaMoYLFactroy
2、用于创建相关的或依赖对象的家族 public Meat createMeat();public YuanLiao createYuanliao();我们接口用于创建一系列的原材料。
创建用于提供原料的接口工厂:RoujiaMoYLFactory.java
各自分店实现接口,完成原料提供:XianRoujiaMoYLFoctory.java
准备时,使用官方的原料:RoujiaMo.java
* 准备工作
public void prepare (
RoujiaMoYLFactory roujiaMoYLFactory ) {
Meet meet =
roujiaMoYLFactory .
creatMeet ();
YuanLiao yuanLiao =
roujiaMoYLFactory .
creatYuanLiao ();
Log .
e (
"---RoujiaMo:" ,
"使用官方的原料 ---" +
name +
": 揉面-剁肉-完成准备工作 yuanLiao:" +
meet +
"yuanLiao:" +
yuanLiao );
3. 单例设计模式
单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例 。
定义:只需要三步就可以保证对象的唯一性
(1) 不允许其他程序用new对象
(2) 在该类中创建对象
(3) 对外提供一个可以让其他程序获取该对象的方法
对比定义:
(1) 私有化该类的构造函数
(2) 通过new在本类中创建一个本类对象
(3) 定义一个公有的方法,将在该类中所创建的对象返回
饿汉式[可用]:SingletonEHan.java
含懒汉式[双重校验锁 推荐用]:SingletonLanHan.java
private SingletonLanHan () {}
private static SingletonLanHan singletonLanHanFour ;
public static SingletonLanHan getSingletonLanHanFour () {
if (singletonLanHanFour == null ) {
synchronized (SingletonLanHan .class ) {
if (singletonLanHanFour == null ) {
singletonLanHanFour = new SingletonLanHan ();
return singletonLanHanFour ;
内部类[推荐用]:SingletonIn.java
枚举[推荐用]:SingletonEnum.java
4. 策略模式
策略模式:定义了算法族,分别封装起来,让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。
以创建游戏角色为例子:
最初的游戏角色的父类:Role.java
发现有重复代码后,重构后的父类:Role.java
1、封装变化(把可能变化的代码封装起来)
2、多用组合,少用继承(我们使用组合的方式,为客户设置了算法)
3、针对接口编程,不针对实现(对于Role类的设计完全的针对角色,和技能的实现没有关系)
最后测试:创建角色:
RoleA roleA = new RoleA ("---A" );
roleA .setiDisplayBehavior (new DisplayYZ ())
.setiAttackBehavior (new AttackXL ())
.setiDefendBehavior (new DefendTMS ())
.setiRunBehavior (new RunJCTQ ());
roleA .display ();// 样子
roleA .attack ();// 攻击
roleA .run ();// 逃跑
roleA .defend ();// 防御
5. 适配器模式
定义:将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。
以充电器为实例: 手机充电器一般都是5V左右吧,咱天朝的家用交流电压220V,所以手机充电需要一个适配器(降压器)
一部手机: Mobile.java
手机依赖一个提供5V电压的接口: V5Power.java
我们拥有的是220V家用交流电: V220Power.java
适配器,完成220V转5V的作用 :V5PowerAdapter.java
最后测试:给手机冲个电:
Mobile mobile = new Mobile ();
V5Power v5Power = new V5PowerAdapter (new V200Power ());
mobile .inputPower (v5Power );
6. 命令模式
定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象,将动作请求者和动作执行者解耦。)
需求:最近智能家电很火热,假设现在有电视、电脑、电灯等家电,现在需要你做个遥控器控制所有家电的开关,要求做到每个按钮对应的功能供用户个性化,对于新买入家电要有非常强的扩展性。
1、家电的API:Door.java
2、把命令封装成类:
统一的命令接口:Command.java
家电实现该接口:DoorOpenCommand.java
3、遥控器:ControlPanel.java
4、定义一个命令,可以干一系列的事情:QuickCommand.java
QuickCommand quickCloseCommand = new QuickCommand (new Command []{new LightOffCommand (light ), new ComputerOffCommand (computer ), new DoorCloseCommand (door )});
controlPanel .setCommands (6 , quickOpenCommand );
controlPanel .keyPressed (6 );
5、遥控器面板执行:CommandActivity.java
controlPanel .setCommands (0 , new DoorOpenCommand (door ));// 开门
controlPanel .keyPressed (0 );
7. 装饰者模式
装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。
先简单描述下装饰者模式发挥作用的地方,当我们设计好了一个类,我们需要给这个类添加一些辅助的功能,并且不希望改变这个类的代码,这时候就是装饰者模式大展雄威的时候了。这里还体现了一个原则:类应该对扩展开放,对修改关闭。
需求:设计游戏的装备系统,基本要求,要可以计算出每种装备在镶嵌了各种宝石后的攻击力和描述:
1、装备的超类:IEquip.java
2、各个装备的实现类:
eg:武器 的实现类: ArmEquip.java
3、装饰品的超类(装饰品也属于装备):IEquipDecorator.java
4、装饰品的实现类:
eg:蓝宝石 的实现类(可累加): BlueGemDecorator.java
5、最后测试:计算攻击力和查看描述:
Log .e ("---" , "一个镶嵌2颗红宝石,1颗蓝宝石的靴子: " );
IEquip iEquip = new RedGemDecorator (new RedGemDecorator (new BlueGemDecorator (new ShoeEquip ())));
Log .e ("---" , "攻击力:" + iEquip .caculateAttack ());
Log .e ("---" , "描述语:" + iEquip .description ());
8. 外观模式
定义:提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层的接口,让子系统更容易使用。其实就是为了方便客户的使用,把一群操作,封装成一个方法。
需求:我比较喜欢看电影,于是买了投影仪、电脑、音响、设计了房间的灯光、买了爆米花机,然后我想看电影的时候,我需要一键观影和一键关闭。
每个设备类的开关等操作:
eg: 爆米花机:PopcornPopper.java
电影院类:HomeTheaterFacade.java
* 一键观影
public void watchMovie () {
computer .
on ();
light .
down ();
popcornPopper .
on ();
popcornPopper .
makePopcorn ();
projector .
on ();
projector .
open ();
player .
on ();
player .
make3DListener ();
最后测试:一键观影:
new HomeTheaterFacade (computer , light , player , popcornPopper , projector ).watchMovie ();
9. 模板方法模式
定义:定义了一个算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以在不改变算法结构的情况下,重新定义算法的步骤。
需求:简单描述一下:本公司有程序猿、测试、HR、项目经理等人,下面使用模版方法模式,记录下所有人员的上班情况
模板方法模式中的三类角色
1、具体方法(Concrete Method)
2、抽象方法(Abstract Method)
3、钩子方法(Hook Method)
工人的超类:Worker.java
// 具体方法
public final void workOneDay () {
Log .e ("workOneDay" , "-----------------work start----------------" );
enterCompany ();
work ();
exitCompany ();
Log .e ("workOneDay" , "-----------------work end----------------" );
// 工作 抽象方法
public abstract void work ();
// 钩子方法
public boolean isNeedPrintDate () {
return false ;
private void exitCompany () {
if (isNeedPrintDate ()) {
Log .e ("exitCompany" , "---" + new Date ().toLocaleString () + "--->" );
Log .e ("exitCompany" , name + "---离开公司" );
程序员实现类(可得知时间):ITWorker.java
* 重写父类的此方法,使可以查看离开公司时间
@ Override
public boolean isNeedPrintDate () {
return true ;
最后测试:
查看所有人员的工作情况:
QAWorker qaWorker = new QAWorker ("测试人员" );
qaWorker ();
HRWorker hrWorker = new HRWorker ("莉莉姐" );
hrWorker .workOneDay ();
查看程序猿离开公司的时间:
ITWorker itWorker = new ITWorker ("jingbin" );
itWorker .workOneDay ();
public void turnCrank () {
currentState .turnCrank ();
if (currentState == soldState || currentState == winnerState ) {
currentState .dispense ();//两种情况会出货
// 出商品
public void dispense () {
Log .e ("VendingMachineBetter" , "---发出一件商品" );
if (count > 0 ) {
count --;
// 设置对应状态
public void setState (State state ) {
this .currentState = state ;
状态的接口:State.java
对应状态的接口实现类:
eg: 中奖状态:WinnerState.java
eg: 售卖状态:SoldState.java
改进后的售货机测试:
// 初始化售货机,且里面有3个商品
VendingMachineBetter machineBetter = new VendingMachineBetter (3 );
machineBetter .insertMoney ();
machineBetter .turnCrank ();
11. 建造者模式
建造模式是对象的创建模式。建造模式可以将一个产品的内部表象(internal representation)与产品的生产过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
需求:用户去汽车店购买汽车。
分析:汽车店根据每个用户的需求提取对应汽车
建造者超类:Builder
public
abstract class Builder {
public abstract void setPart (String name , String type );
public abstract Product getProduct ();
建造者对应实现类:ConcreteBuilder
public class ConcreteBuilder extends Builder {
private Product product = new Product ();
@ Override
public void setPart (String name , String type ) {
product .setName (name );
product .setType (type );
@ Override
public Product getProduct () {
return product ;
店长Director 取汽车:
// 店长
Director director = new Director ();
// 得到宝马汽车,内部实现提取宝马汽车的详情操作
Product product = director .getBProduct ();
// 展示汽车信息
product .showProduct ();
12. 原型模式
原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
以获取多种形状为例,共分四步:
1、创建一个实现了 Cloneable 接口的抽象类。Shape (implements Cloneable)
public abstract class Shape implements Cloneable {
private String id ;
protected String type ;
public abstract void draw ();
public String getId () {
return id ;
public void setId (String id ) {
this .id = id ;
@ Override
public Object clone () {
Object object = null ;
try {
object = super .clone ();
} catch (CloneNotSupportedException e ) {
Log .e ("--" , e .getMessage ());
return object ;
2、创建扩展了上面抽象类的实体类。Circle 、Rectangle 、Square
public class Circle extends Shape {
public Circle () {
type = "Circle" ;
@ Override
public void draw () {
Log .e ("---" , "Inside Circle::draw() method." );
3、创建一个类,从数据库获取实体类,并把它们存储在一个 Hashtable 中。ShapeCache
public class ShapeCache {
private static Hashtable <String , Shape > shapeMap = new Hashtable <String , Shape >();
public static Shape getShape (String shapeId ) {
Shape shapeCache = shapeMap .get (shapeId );
return (Shape ) shapeCache .clone ();
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
public static void loadCache () {
Circle circle = new Circle ();
circle .setId ("1" );
shapeMap .put (circle .getId (), circle );
Rectangle rectangle = new Rectangle ();
rectangle .setId ("2" );
shapeMap .put (rectangle .getId (), rectangle );
Square square = new Square ();
square .setId ("3" );
shapeMap .put (square .getId (), square );
4、使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
// 使用 ShapeCache 类来获取存储在 Hashtable 中的形状的克隆。
ShapeCache .loadCache ();
Shape shapeCache1 = ShapeCache .getShape ("1" );
Shape shapeCache2 = ShapeCache .getShape ("2" );
Shape shapeCache3 = ShapeCache .getShape ("3" );
13. 享元模式
主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。我们将通过创建 5 个对象来画出 20 个分布于不同位置的圆来演示这种模式。由于只有 5 种可用的颜色,所以 color 属性被用来检查现有的 Circle 对象。
主要解决 :在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
以随机获取多种形状为例,共分四步:
1、创建一个接口。
public interface Shape {
void draw ();
2、创建实现接口的实体类。
public class Circle implements Shape {
private String color ;
private int x ;
private int y ;
private int radius ;
public Circle (String color ) {
this .color = color ;
public void setX (int x ) {
this .x = x ;
public void setY (int y ) {
this .y = y ;
public void setRadius (int radius ) {
this .radius = radius ;
@ Override
public void draw () {
Log .e ("---" , "Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius );
3、创建一个工厂,生成基于给定信息的实体类的对象。
public
class ShapeFactory {
private static final HashMap <String , Shape > circleMap = new HashMap <String , Shape >();
public static Shape getShape (String color ) {
Shape shape = circleMap .get (color );
if (shape == null ) {
shape = new Circle (color );
circleMap .put (color , shape );
Log .e ("getShape" , "Creating circle of color : " + color );
return shape ;
4、使用该工厂,通过传递颜色信息来获取实体类的对象。
for (int i = 0 ; i < 20 ; i ++) {
Circle circle = (Circle ) ShapeFactory .getShape (getRandomColor ());
circle .setX (getRandomX ());
circle .setY (getRandomY ());
circle .setRadius (100 );
circle .draw ();
14. 代理模式
一个类代表另一个类的功能。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。可以理解为内存中没有这个对象就创建,有就直接返回这个对象。
主要解决 :在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
以获取磁盘中的图片为例,总共分三步:
1、创建一个接口。
public interface Image {
void display ();
2、创建实现接口的实体类 RealImage。对应代理类:ProxyImage。
public class RealImage implements Image {
private String fileName ;
public RealImage (String fileName ) {
this .fileName = fileName ;
loadFromDisk (fileName );
private void loadFromDisk (String fileName ) {
Log .e ("RealImage" , "loading " + fileName );
@ Override
public void display () {
Log .e ("RealImage" , "Displaying " + fileName );
public class ProxyImage implements Image {
private String fileName ;
private RealImage realImage ;
public ProxyImage (String fileName ) {
this .fileName = fileName ;
@ Override
public void display () {
if (realImage == null ) {
realImage = new RealImage (fileName );
realImage .display ();
3、当被请求时,使用 ProxyImage 来获取 RealImage 类的对象。
Image image = new ProxyImage ("test_10mb.png" );
// 第一次是new的,图像从磁盘加载
image .display ();
// 第二次取缓存,图像不需要从磁盘加载
image .display ();
15. 桥接模式
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
主要解决 :在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
以画不同颜色的圆为例,实现共分五步:
1、创建桥接实现接口。
public interface DrawAPI {
void drawCircle (int radius , int x , int y );
2、创建实现了 DrawAPI 接口的实体桥接实现类。RedCircle 、GreenCircle
public class RedCircle implements DrawAPI {
@ Override
public void drawCircle (int radius , int x , int y ) {
Log .e ("---" , "Drawing Circle[ color: red, radius: "
+ radius + ", x: " + x + ", " + y + "]" );
3、使用 DrawAPI 接口创建抽象类 Shape 。
public abstract class Shape {
protected DrawAPI drawAPI ;
protected Shape (DrawAPI drawAPI ) {
this .drawAPI = drawAPI ;
public abstract void draw ();
4、创建实现了 Shape 接口的实体类。
public class Circle extends Shape {
private int x , y , radius ;
protected Circle (int x , int y , int radius , DrawAPI drawAPI ) {
super (drawAPI );
this .x = x ;
this .y = y ;
this .radius = radius ;
@ Override
public void draw () {
drawAPI .drawCircle (radius , x , y );
5、使用 Shape 和 DrawAPI 类画出不同颜色的圆。
// 画红圆
Circle circle = new Circle (10 , 10 , 100 , new RedCircle ());s
circle .draw ();
// 画绿圆
Circle circle2 = new Circle (20 , 20 , 100 , new GreenCircle ());
circle2 .draw ();
16. 组合模式
又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
主要解决 :它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
以创建和打印员工的层次结构为例,最小单元示例:
1、创建 Employee 类,该类带有 Employee 对象的列表。
public class
Employee {
private String name ;
// 部门
private String dept ;
// 工资
private int salary ;
// 员工 list
private List <Employee > subordinates ;
public Employee (String name , String dept , int salary ) {
this .name = name ;
this .dept = dept ;
this .salary = salary ;
this .subordinates = new ArrayList <Employee >();
public void add (Employee e ) {
subordinates .add (e );
public void remove (Employee e ) {
subordinates .remove (e );
public List <Employee > getSubordinates () {
return subordinates ;
@ Override
public String toString () {
return "Employee{" +
"name='" + name + '\'' +
", dept='" + dept + '\'' +
", salary=" + salary +
", subordinates=" + subordinates +
'}' ;
2.使用 Employee 类来创建和打印员工的层次结构。
final Employee ceo = new Employee ("John" , "CEO" , 30000 );
Employee headSales = new Employee ("Robert" , "Head sales" , 20000 );
Employee headMarketing = new Employee ("Michel" , "Head Marketing" , 20000 );
Employee clerk1 = new Employee ("Laura" , "Marketing" , 10000 );
Employee clerk2 = new Employee ("Bob" , "Marketing" , 10000 );
Employee salesExecutive1 = new Employee ("Richard" , "Sales" , 10000 );
Employee salesExecutive2 = new Employee ("Rob" , "Sales" , 10000 );
ceo .add (headSales );
ceo .add (headMarketing );
headSales .add (salesExecutive1 );
headSales .add (salesExecutive2 );
headMarketing .add (clerk1 );
headMarketing .add (clerk2 );
Log .e ("---" , ceo .toString ());
// 打印
* Employee{name='John', dept='CEO', salary=30000,
* subordinates=[Employee{name='Robert', dept='Head sales', salary=20000,
* subordinates=[
* Employee{name='Richard', dept='Sales', salary=10000, subordinates=[]},
* Employee{name='Rob', dept='Sales', salary=10000, subordinates=[]}]},
* Employee{name='Michel', dept='Head Marketing', salary=20000,
* subordinates=[Employee{name='Laura', dept='Marketing', salary=10000, subordinates=[]},
* Employee{name='Bob', dept='Marketing', salary=10000, subordinates=[]}]}]}
17. 迭代器模式
Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。迭代器模式属于行为型模式。
主要解决 :不同的方式来遍历整个整合对象。
以使用迭代器打印名字为例,总共分三步:
1、创建接口:
public interface Iterator {
public boolean hasNext ();
public Object next ();
public interface Container {
public Iterator getIterator ();
2、创建实现了 Container 接口的实体类。该类有实现了 Iterator 接口的内部类 NameIterator。
public class NameRepository implements Container {
private String names [] = {"John" , "jingbin" , "youlookwhat" , "lookthis" };
@ Override
public Iterator getIterator () {
return new NameIterator ();
private class NameIterator implements Iterator {
int index ;
@ Override
public boolean hasNext () {
if (index < names .length ) {
return true ;
return false ;
@ Override
public Object next () {
if (hasNext ()) {
return names [index ++];
return null ;
3、使用 NameRepository 来获取迭代器,并打印名字。
NameRepository nameRepository = new NameRepository ();
for (Iterator iterator = nameRepository .getIterator (); iterator .hasNext (); ) {
String name = (String ) iterator .next ();
Log .e ("---" , name );
* /---: John
* /---: jingbin
* /---: youlookwhat
* /---: lookthis
18. 中介者模式
用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
主要解决 :对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
以公共聊天室为例,最小单元示例步骤:
1、创建中介类。
public class CharRoom {
public static void showMessage (User user , String message ) {
Log .e ("---" , new Date ().toString ()
+ " [" + user .getName () + "] : " + message );
2、创建 user 类。
public class User {
private String name ;
public User (String name ) {
this .name = name ;
public String getName () {
return name ;
public void setName (String name ) {
this .name = name ;
public void sendMessage (String message ) {
// 使用中介类
CharRoom .showMessage (this , message );
3、使用 User 对象来显示他们之间的通信。
User jingbin
= new User ("jingbin" );
jingbin .sendMessage ("Hi~ youlookwhat!" );
//---: Sun Feb 02 08:11:47 GMT+00:00 2020 [jingbin] : Hi~ youlookwhat!
User jingbin = new User ("youlookwhat" );
jingbin .sendMessage ("Hi~ jingbin!" );
//---: Sun Feb 02 08:11:49 GMT+00:00 2020 [youlookwhat] : Hi~ jingbin!
19. 备忘录模式
保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
主要解决 :所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
以使用备忘录为例,最小单元步骤:
1、创建 备忘录 Memento 类。
public class Memento {
private String state ;
public Memento (String state ) {
this .state = state ;
public String getState () {
return state ;
public void setState (String state ) {
this .state = state ;
2、创建 Originator 类。
public class Originator {
private String state ;
public String getState () {
return state ;
public void setState (String state ) {
this .state = state ;
public Memento setSateToMemento () {
return new Memento (state );
public String getStateFromMemento (Memento memento ) {
return memento .getState ();
3、创建 CareTaker 类。
public class CareTaker {
private List <Memento > mementoList = new ArrayList <Memento >();
public void add (Memento memento ) {
mementoList .add (memento );
public Memento get (int index ) {
return mementoList .get (index );
4、使用 CareTaker 和 Originator 对象。
// 管理者
CareTaker careTaker = new CareTaker ();
Originator originator = new Originator ();
originator .setState ("State #1" );
originator .setState ("State #2" );
// 保存状态
careTaker .add (originator .setSateToMemento ());
originator .setState ("State #3" );
// 保存状态
careTaker .add (originator .setSateToMemento ());
originator .setState ("State #4" );
Log .e ("---" , "Current State: " + originator .getState ());
// 得到保存的状态
String fromMemento1 = originator .getStateFromMemento (careTaker .get (0 ));
Log .e ("---" , "First Saved State: " + fromMemento1 );
String fromMemento2 = originator .getStateFromMemento (careTaker .get (1 ));
Log .e ("---" , "Second Saved State: " + fromMemento2 );
* /---: Current State: State #4
* /---: First Saved State: State #2
* /---: Second Saved State: State #3
20. 解释器模式
提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
主要解决 :对于一些固定文法构建一个解释句子的解释器。
以解释一句话为例,最小单元步骤:
1、创建一个表达式接口 Expression。
public interface Expression {
public boolean interpreter (String content );
2、创建实现了上述接口的实体类。TerminalExpression、OrExpression、AndExpression。
public class TerminalExpression implements Expression {
private String data ;
public TerminalExpression (String data ) {
this .data = data ;
@ Override
public boolean interpreter (String content ) {
// 是包含判断
return content .contains (data );
public class OrExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public OrExpression (Expression expression1 , Expression expression2 ) {
this .expression1 = expression1 ;
this .expression2 = expression2 ;
@ Override
public boolean interpreter (String content ) {
return expression1 .interpreter (content ) || expression2 .interpreter (content );
public class AndExpression implements Expression {
private Expression expression1 ;
private Expression expression2 ;
public AndExpression (Expression expression1 , Expression expression2 ) {
this .expression1 = expression1 ;
this .expression2 = expression2 ;
@ Override
public boolean interpreter (String content ) {
return expression1 .interpreter (content ) && expression2 .interpreter (content );
3、使用 Expression 类来创建规则,并解析它们。
* 规则:jingbin 和 youlookwhat 是男性
public static Expression getMaleExpression () {
TerminalExpression jingbin = new TerminalExpression ("jingbin" );
TerminalExpression youlookwhat = new TerminalExpression ("youlookwhat" );
return new OrExpression (jingbin , youlookwhat );
* 规则:Julie 是一个已婚的女性
public static Expression getMarriedWomanExpression () {
TerminalExpression julie = new TerminalExpression ("Julie" );
TerminalExpression married = new TerminalExpression ("Married" );
return new AndExpression (julie , married );
Expression maleExpression = getMaleExpression ();
// jingbin is male: true
Log .e ("---" , "jingbin is male: " + maleExpression .interpreter
("jingbin" ));
Expression womanExpression = getMarriedWomanExpression ();
// Julie is married woman: true
Log .e ("---" , "Julie is married woman: " + womanExpression .interpreter ("Married Julie" ));
21. 责任链模式
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
主要解决 :职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
以Android Studio中打印日志为例,最小单元步骤:
1、创建抽象的记录器类 AbstractLogger。
public abstract class AbstractLogger {
public static int INFO = 1 ;
public static int DEBUG = 2 ;
public static int ERROR = 3 ;
protected int level ;
// 责任链中的下一个元素
protected AbstractLogger nextLogger ;
public void setNextLogger (AbstractLogger nextLogger ) {
this .nextLogger = nextLogger ;
public void logMessage (int level , String message ) {
if (this .level <= level ) {
write (message );
// 递归效果,不断调用下一级 logMessage
if (nextLogger != null ) {
nextLogger .logMessage (level , message );
protected abstract void write (String message );
2、创建扩展了该记录器类的实体类。
public class ConsoleLogger extends AbstractLogger {
public ConsoleLogger (int level ) {
this .level = level ;
@ Override
protected void write (String message ) {
Log .e ("---" , "Standard Console::Logger " + message );
public class FileLogger extends AbstractLogger {
public FileLogger (int level ) {
this .level = level ;
@ Override
protected void write (String message ) {
Log .e ("---" , "File::Logger " + message );
public class ErrorLogger extends AbstractLogger {
public ErrorLogger (int level ) {
this .level = level ;
@ Override
protected void write (String message ) {
Log .e ("---" , "Error Console::Logger " + message );
3、创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。
public static AbstractLogger getChainOfLoggers () {
ErrorLogger errorLogger = new ErrorLogger (AbstractLogger .ERROR );
FileLogger fileLogger = new FileLogger (AbstractLogger .DEBUG );
ConsoleLogger consoleLogger = new ConsoleLogger (AbstractLogger .INFO );
errorLogger .setNextLogger (fileLogger );
fileLogger .setNextLogger (consoleLogger );
return errorLogger ;
AbstractLogger logger = getChainOfLoggers ();
// ---: Standard Console::Logger this is an information.
logger .logMessage (AbstractLogger .INFO , "this is an information." );
// ---: File::Logger this is a debug level information.
// ---: Standard Console::Logger this is a debug level information.
logger .logMessage (AbstractLogger .DEBUG , "this is a debug level information." );
// ---: Error Console::Logger this is a error level information.
// ---: File::Logger this is a error level information.
// ---: Standard Console::Logger this is a error level information.
logger .logMessage (AbstractLogger .ERROR , "this is a error level information." );
22. 访问者模式
在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
主要解决 :稳定的数据结构和易变的操作耦合问题。
以显示计算机的组成部分为例,主要分五步实现:
1、定义一个表示元素的接口。
public interface ComputerPart {
public void accept (ComputerPartVisitor computerPartVisitor );
2、创建扩展了上述类的实体类。Keyboard 、Monitor 、Mouse 、Computer
public class Computer implements ComputerPart {
private ComputerPart [] parts ;
public Computer () {
this .parts = new ComputerPart []{new Mouse (), new Keyboard (), new Monitor ()};
@ Override
public void accept (ComputerPartVisitor computerPartVisitor ) {
for (ComputerPart part : parts ) {
part .accept (computerPartVisitor );
computerPartVisitor .visit (this );
public class Mouse implements ComputerPart {
@ Override
public void accept (ComputerPartVisitor computerPartVisitor ) {
computerPartVisitor .visit (this );
3、定义一个表示访问者的接口。
public interface ComputerPartVisitor {
public void visit (Computer computer );
public void visit (Mouse mouse );
public void visit (Keyboard keyboard );
public void visit (Monitor monitor );
4、创建实现了上述类的实体访问者。
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@ Override
public void visit (Computer computer ) {
Log .e ("---" , "Displaying Computer." );
@ Override
public void visit (Mouse mouse ) {
Log .e ("---" , "Displaying Mouse." );
@ Override
public void visit (Keyboard keyboard ) {
Log .e ("---" , "Displaying Keyboard." );
@ Override
public void visit (Monitor monitor ) {
Log .e ("---" , "Displaying Monitor." );
5、使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。