1. 如何判断你已经掌握了某种设计模式?(非常重要)
- ① 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
- ② 它是如何解决的?掌握它的结构图,记住它的关键代码
- ③ 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- ④ 这个模式的缺点是什么?在使用时要注意什么
一、外观模式
1. 这个模式的意图是什么?它解决了什么问题、什么时候可以使用它
- 什么时候使用它:
-
在客户端
与 一系列子系统
有较为复杂交互时,可以引入外观角色
,为复杂的子系统提供一个统一的入口,使子系统与客户端的耦合度降低。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
- 结构图:
-
Facade(外观角色):
在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。
-
SubSystem(子系统角色):
在软件系统中可以有一个或者多个子系统角色;对于子系统而言,并不知道外观角色的存在,仅仅认为外观角色也是一个客户端而已。
class SubSystemA
{
public void MethodA()
{
//业务实现代码
}
}
class SubSystemB
{
public void MethodB()
{
//业务实现代码
}
}
class SubSystemC
{
public void MethodC()
{
//业务实现代码
}
}
class Facade
{
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();
public void Method()
{
obj1.MethodA();
obj2.MethodB();
obj3.MethodC();
}
}
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- 生活中的:
- ① 在家泡茶,需要自己使用茶具、烧水、放茶叶等等操作
- ② 去店里泡茶,只需要告诉服务员需要什么茶;服务员充当
外观角色
,去处理茶壶、茶叶、烧水等操作
- 软件中的:很多网页都有一个首页导航栏充当
外观角色
,将不同需求的用户引导至不通的子功能模块。
4. 这个模式的缺点是什么?在使用时要注意什么
- 缺点:
- 客户直接调用外观角色,从一定程度虽然简化了和子系统的交互,但是也是削减了子系统的灵活性
二、代理模式
1. 这个设计模式的意图是什么?它解决了什么问题、什么时候可以使用它
- 什么时候可以使用它:
- 由于某些原因,客户端不想或不能直接访问一个对象,此时可以通过称之为
"代理"
的第三者来实现间接访问,该方案对应的设计模式称为代理模式。
2. 它是如何解决的?掌握它的结构图,记住它的关键代码
image.png
- 结构图:
-
Subject(抽象主题角色):
它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
-
Proxy(代理主题角色):
它包含了对真实主题的引用,并且实现了抽象主题的接口。通常在代理角色中,客户端在调用所引用的真实主题操作之前或者之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象的操作。
-
RealSubject(真实主题角色):
它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
abstract class Subject
{
public abstract void Request();
}
class RealSubject : Subject
{
public override void Request()
{
//业务方法具体实现代码
}
}
class Proxy : Subject
{
private RealSubject realSubject = new RealSubject(); //维持一个对真实主题对象的引用
public void PreRequest()
{
…...
}
public override void Request()
{
PreRequest();
realSubject.Request(); //调用真实主题对象的方法
PostRequest();
}
public void PostRequest()
{
……
}
}
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- 软件中的:保护代理、缓冲代理、智能引用代理、 远程代理、虚拟代理
- 生活中的:代购网站
4. 这个模式的缺点是什么?在使用时要注意什么
- 由于在客户端和真实主题之家增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
三、命令模式
1. 这个设计模式的意图是什么?它解决了什么问题、什么时候使用它
- 什么时候使用它:
- 在软件开发中,我们经常需要将请求发送者和接收者完全解耦,让
发送者
和接收者
直接没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
2. 它是如何解决的?掌握它的机构图,记住它的关键代码
image.png
- 结构图:
-
Command(抽象命令类):
抽象命令类一般是一个抽象类或者接口,在其中声明了用于执行请求的 execute()
等方法,通过这些方法可以调用请求接收者的相关操作。
-
ConcreteCommand(具体命令类):
具体命令类是抽象命令类的子类,实现了抽象命令类中声明的方法,它对应具体的接收对象,将接收对象的动作绑定其中。在实现 execute()
方法时,将调用接收者对象的相关操作。
-
Invoker(调用者):
调用者即请求的发送者,它通过命令对象
来执行请求。
-
Receiver(接收者):
接收者执行与请求相关的操作,它具体实现对请求的业务处理。
命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分割开。
每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行相应的操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。
abstract class Command {
public abstract void execute();
}
class Invoker {
private Command command;
//构造注入
public Invoker(Command command) {
this.command = command;
}
//设值注入
public void setCommand(Command command) {
this.command = command;
}
//业务方法,用于调用命令类的execute()方法
public void call() {
command.execute();
}
}
class ConcreteCommand extends Command {
private Receiver receiver; //维持一个对请求接收者对象的引用
public void execute() {
receiver.action(); //调用请求接收者的业务处理方法action()
}
}
class Receiver {
public void action() {
//具体操作
}
}
3. 至少能够想到它的两个应用实例,一个生活中的,一个软件中的
- 软件中的:命令队列的实现、撤销操作的实现、日志恢复系统
- 生活中的:
开关(发送者)
可以通过 线(命令角色)
控制 灯泡或音响(接收者)
4. 这个模式的缺点是什么?在使用时要注意什么
-
使用命令模式可能会导致某些系统有过多的具体命令类。
因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。
网友评论