一分钟讲清楚一个设计模式

大家对设计模式都不陌生,在工作中有意无意多少会用到一些设计模式。但是,面对新人,我们是否能够用一分钟时间向他讲解明白一种设计模式呢?或者在述职的时候,我们又是否能够很精炼的用一分钟时间说清楚项目中是如何使用某种设计模式呢?

今天,我们就用日常交流的话语来总结下GoF的23种设计模式。在讲设计模式之前,我们需要先了解下设计模式的本质、作用、设计原则和分类。

一、设计模式的本质

设计模式的本质是面向对象设计原则在实际项目中的运用。

二、设计模式的意义

1、对程序员而言:提高思维能力、设计能力;

2、对项目而言:更加标准化、提高开发效率;

3、对软件而言:代码高可靠性、高重用性、可读性好。

三、设计模式的原则

1、开闭原则:开放扩展、关闭修改;

2、里氏代换:基类出现的地方,子类也可以出现;(开闭的补充)

3、依赖倒转:针对接口(抽象类)设计和编程,而不是依赖于具体的是实现类;(开闭的基础)

4、接口隔离:多个“隔离的接口”比“单个接口”好;

5、最少知道(迪米特):实体里的元素尽量保持私有

6、合成服用:组合优于继承

一句话:开闭是共识,里氏是基础,依赖是补充;其他三个:接口(接口相关)、最少(类相关)、合成(结构相关)

四、分类

1、创建型5个(创建对象但隐藏创建逻辑)

工厂、抽象工厂、单例、建造者、原型

2、结构型7个(关注类和对象的组合)

适配器、桥接、过滤器、组合、装饰器、外观、享元、代理

3、 行为型11个(关注对象间的通信)

责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、空对象、策略、模板、访问者

五、一分钟一个设计模式

(一)创建型

1、单例(Singleton)模式

一个类只能生成一个实例。通过构造函数私有,静态方法返回私有静态实例实现单例模式。分“懒汉”和“饿汉”两类,懒汉的实现又有线程安全和不安全的问题。线程安全的实现有synchronized、双重校验锁和静态内部类三种方式。

2、原型(Prototype)模式

把一个对象用克隆的方式生成另一个对象,而不是通过new的方式实现。分为浅克隆和深克隆,浅克隆是指克隆的对象的引用类型的属性不克隆,而是指向原对象的属性地址,深克隆相反。

3、简单工厂(Factory)模式

不采用通常new的方式生成对象,而是使用一个专门的工厂负责生产对象,这个工厂类一般提供一个静态方法,比如makeProduct,方法的参数是获取对象的类型,直接通过工厂类点makeProduct的方式获取需要的对象。简单工厂生产的产品是统一的抽象产品,方便外部调用者可以提供通用的处理方式。

工厂方法(Factory Method)模式

相比简单工厂只是讲产品抽象,工厂方法模式将工厂也抽象化了,不同的产品由不同的具体工厂负责生产。满足了依赖倒置原则,软件设计不依赖于具体的工厂类,使用抽象工厂就可以完成设计。

4、抽象工厂(AbstractFactory)模式

工厂方法模式只能生产一类产品,而实际开发中我们需要的可能是一系列关联的产品对象,这就用到了抽象工厂模式。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

5、建造者(Builder)模式

建造者模式强调的是把复杂对象的创造分解为多个部分进行创建。创建过程由指挥者Director发起,具体的创建者叫做Builder,它可以创建Prodcut的各个部分。指挥者Direcotor调用Builder创建Product的各个部分,并将各个部分装配成需要的Prodcut。

一分钟理解6种创建型模式

这6种模式总体是从一到多的过程:一个对象是“单例”,一个对象复制多个是“原型”,一个工厂生产多个对象是“简单工厂”,多个工厂生产多个单产品是“工厂方法”,多个工厂生产多个产品族是“抽象工厂”,把产品分解为多个部分是“建造者”。

(二)构造型

1、代理(Proxy)模式

为了保护某些类,这里叫做主题类,或者为了使其更好用,不直接使用这些主题类,而是构建了一个代理类。代理类提供了与主题类相同的接口,在代理类内部调用主题类。比如不对数据库连接直接使用,而是将其连接封装到一个代理类里。

2、适配器(Adapter)模式

场景是已经存在了一些可用的接口Target,和可用的具体类,但是具体类的却不能直接实现Target接口,导致无法使用。这时就需要创建一个适配器类Adapter,它内部封装具体类,此时叫做适配者类Adaptee,然后把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

3、桥接(Bridge)模式

接口继承是子接口继承自父接口,桥接模式使用组合关系代替了继承关系,子接口不再继承自父接口,而是作为父接口的一个属性,子接口定义的一些新属性以这样的方式供父接口使用。这样的好处是在类维度比较多的情况下,可以避免子类过多的问题。这里的父接口叫做抽象化Abstraction,子接口叫做实现化Implementor。

4、装饰(Decorator)模式

首先有个构件Component,要给它添加一些职责,可以提供一系列装饰类Decorator。通过装饰类装饰后,我们只希望构件的职责增加,但类型不变,还是原来的构件类型。需要让装饰接口也继承自构件接口,这样在使用的时候,只需要new一个装饰类,同时把构件作为构造函数的参数传递进去,返回的依然是一个可用的构件类型。

 

5、外观(Facade)模式

外观就是门面或窗口,不管内部多个子系统多复杂,对外只提供一个统一的外观类。外观类封装了各子系统的功能,对外提供统一的接口。

6、享元(Flyweight)模式

一个对象里有些状态是基本不改变的,有些状态会经常改变。把常改变的部分提取出来,叫做非享元,剩下的不改变的抽象成享元,非享元作为享元的一个属性存在。然后,提供一个享元工厂,根据需要它可以提供合适的享元对象,并将非享元传递给享元,让享元具有了合适的完整状态。这样的好处是节省了大量的系统资源。

7、组合(Composite)模式

将对象组装成树状层次结构,有树叶构件Leaf和树枝构件Composite的概念,他们都继承自同一个抽象构件Component。树枝可以添加树叶,树叶不行。分为透明和安全两种方式,透明方式是把add、remove等方法定义到Component,用户无需区别树叶和树枝;安全方式是把方法定义到Composite里,但客户需要区分树枝树叶,失去了透明性。

一分钟理解7种构造型模式

对已有类进行包装的:代理、装饰、适配器、外观。代理侧重于对现有类的保护和改造,装饰是对现有类职责进行增加,适配器侧重于将现有接口和现有类进行关联适配,外观是对现有子系统的封装。

对已有类进行组合的:桥接、享元、组合。桥接是用组合替代继承,享元是把经常变化的状态提取出来抽象成为享元对象的非享元属性,组合是树状结构的实现。

(三)行为型

1. 模板方法(Template Method)模式

父类实现算法骨架,而使用到的一些具体的算法子方法可以在子类中实现。这实际上是子类重写了父类的方法,可重写的包括具体方法、抽象方法、钩子方法。

2. 策略(Strategy)模式

用户使用某个算法时,这个算法可能会有多种实现方式,可以把这些实现都封装起来作为不同的策略Strategy,而用户使用的还是统一的环境类Context。具体使用时,根据情况把具体的策略提供给环境类,然后调取环境类的计算方法即可。

3. 命令(Command)模式

正常使用命令是直接调取对象的方法,但是要把这个命令储存、传递、调用、增加与管理,就需要用到命令模式。命令的使用者叫Invoker,命令的具体执行和实现者叫Receiver,把命令封装到Command就是在Command里实现call方法,call里调取Receiver的action。

4. 职责链(Chain of Responsibility)模式

职责链的每个环节叫做处理者Handler,它包含next属性也是一个处理者,每个处理者在执行完请求handleRequest后会自动调取next执行请求handleRequest,实现一种链式方法执行。具体的职责链各个环节的装配由客户类实现。

5. 状态(State)模式

一个环境类Context如果有多种状态,并且状态的切换具有一定的条件判断,那么可以采用状态模式。将状态抽象为State,每次环境改变后,把自身作为参数传递给状态State的handle方法,State根据条件改变Context的状态为新的状态。

6. 观察者(Observer)模式

当一个对象发生改变后,需要通知其他多个对象进行相应的响应。发生改变的对象叫做主题Subject,它维护了一个抽象观察者Observer的队列observers。需要响应主题的对象只需要实现Observer接口,并添加到observers即可。Subject在需要的时候循环observers依次调取各观察者的响应方法即可。

7. 中介者(Mediator)模式

如果多个对象集合中,任意一个对象发生改变后,都想通知其他对象做出响应,可以用中介者模式。这些对象叫做同事类Colleague,还需建一个中介类Mediator,Mediator维护一个同事列表,每个同事对象也会关联到这个中介mediator。当一个同事A发出send后,会通知中介mediator进行转发relay,中介再循环调用A以外的同事队列,使每个同事都receive消息。

8. 迭代器(Iterator)模式

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。使用比较常见,不做详述。

Iterator it = ag.getIterator();

while (it.hasNext()){

Object ob = it.next();

//do something

}

9. 访问者(Visitor)模式

对于某个复杂的数据结构Object Structure,它包含了一系列的元素Element,而对这些元素的操作方式也不一样并抽象成了访问者Visitor。当数据结构accept一个visitor后,需要让内部的各个元素都accept这个visitor,而元素在accept方法中调取visitor的create方法来实现visitor对元素的操作。

10. 备忘录(Memento)模式

有时候需要用到保存和还原的操作,这时就可以使用备忘录模式。发起人Originator可以将当前状态并生成一个备忘录对象Memento,然后调取管理者Caretaker保存备忘录对象。需要还原的时候,发起人再通过管理者获取到已存的备忘录对象,并改变还原当前状态即可。

11. 解释器(Interpreter)模式

解释器模式可以实现对特定某些的语法进行解释和处理。需要了解的概念有终结符表达式和非终结符表达式。每个表达式Expression都需要实现特定的解释方法interpret,一般通过递归的方式实现一个复杂语句的解释。

12. 一分钟理解11种行为型模式

对方法的覆盖:模板、策略、访问者。模板是子类对父类方法的重写;策略是对环境中关联的策略类进行替换;访问者的数据结构更复杂,需要各子元素实现访问者的访问。

对方法的传递:命令。将方法封装,实现方法的传递和管理。

对象状态改变:备忘录。将状态封装,实现状态保存和还原。

多对象切换:职责链、状态。职责链是多元素按照单链条方式传递,状态是多元素按照有向图结构进行改变。

多对象遍历:观察、中介、迭代。观察是特定对象通知其它对象,中介是任意一个对象通知其它对象,迭代是遍历所有对象。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

目标Web3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值