我认为,本章是重点中的重点。并非23个模式都被广泛应用,其中常用和最为有效的大概有15个模式。

1、适配器(Adapter)

1)、使用场景

使用一个已经存在的类,但如果他的接口,也就是他的方法和你的要求不相同时,考虑使用是适配器模式。

就是说,双方都不修改自己的代码的时候,可以采用适配器模式。

2)、结构图

3)、相关模式

外观对象:隐藏外部系统的资源适配器也被视为外观对象,因为资源适配器使用单一对象封装了对子系统或系统的访问。
资源适配器:当包装对象时为不同外部接口提供适配时,该对象叫资源适配器

4)、准则

类名后缀为“Adapter”。

5)、用到的GRASP原则

 2、工厂模式

1)、使用场景

该模式也常称为“简单工厂”或“具体工厂”。如:
1)、存在复杂创建逻辑
2)、为提高内聚而分离创建者职责(关注点分离)
因此,创建称为工厂的纯虚构对象来处理这些创建职责。

2)、结构

一般xxxFactory应该是单实例类。

3)、相关模式

通常使用 单例模式 来访问工厂模式。

由谁创建工厂呢?一般采用单例模式。

3、单例模式

1)、使用场景

只有唯一实例的类即为“单实例类”。对象需要全局可见性和单点访问。
因此,建议对类定义静态方法用以返回单实例。

2)、相关模式

单例模式:通常用于创建工厂对象和外观对象

以上整合例子:

4、策略模式

1)、使用场景

销售的定价策略(也可叫做规则、政策或算法)具有多样性。在一段时间内,对于所有的销售可能会有10%的折扣,后期可能会对超出200元的销售给予10%的折扣,并且还会存在其他大量的变化。

因此,在单独的类中分别定义每种策略/规则/政策/算法,并且使其具有共同接口

2 )、结构

策略模式,共同的方法内传入的参数,通常是上下文对象,上图就是sale。

3)、结合工厂模式

1)、使用工厂模式创建这些策略类
2)、使用单例模式创建工厂类。

5、组合模式

1)、使用场景

如果有重叠怎么办?比如:
1)老年人折扣20%
2)购物金额满200元享受15%折扣 因此,如何能够处理像原子对象一样,(多态的)处理一组对象或具有组合结构的对象呢?
答:定义组合和原子对象的类,使他们具有相同的接口。

2)、结构

2)、相关模式

通常与策略命令模式一起使用。

6、外观模式

1)、使用场景

对一组完全不同的实现或接口(如子系统中的实现和接口)需要公共、统一的接口,隐藏掉子系统复杂的实现或接口。从而使关注点分离。
如:slf4j、通信前置
其与适配器的区别在于,facade模式针对同职能接口的抽象并提供公共、统一的接口,强度的是统一。而adapter模式针对的是适配不同接口且老接口不改的场景,强调的是适配

2)、结构

3)、例子

class Program
{
static void Main(string[] args)
{
Facade facade = new Facade(); facade.MethodA();
facade.MethodB(); Console.Read(); }
} class SubSystemOne
{
public void MethodOne()
{
Console.WriteLine(" 子系统方法一");
}
} class SubSystemTwo
{
public void MethodTwo()
{
Console.WriteLine(" 子系统方法二");
}
} class SubSystemThree
{
public void MethodThree()
{
Console.WriteLine(" 子系统方法三");
}
} class SubSystemFour
{
public void MethodFour()
{
Console.WriteLine(" 子系统方法四");
}
} class Facade
{
SubSystemOne one;
SubSystemTwo two;
SubSystemThree three;
SubSystemFour four; public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
four = new SubSystemFour();
} public void MethodA()
{
Console.WriteLine("\n方法组A() ---- ");
one.MethodOne();
two.MethodTwo();
four.MethodFour();
} public void MethodB()
{
Console.WriteLine("\n方法组B() ---- ");
two.MethodTwo();
three.MethodThree();
}
}

4)、相关模式

外观模式通常通过单例模式访问。

7、观察者模式(Observer)

1)、定义

观察者模式又叫“发布-订阅(Publish/Subscribe)”模式、又叫“委派事件模型”。
之所以被称为观察者模式,是因为监听器或订阅者在对相应事件进行观察。
之所以被称为委派事件模型,是因为发布者将事件处理委派给了监听器(订阅者)

2)、使用场景

例子:支付成功后,
1)记录日志
2)写数据库
3)前端展示支付结果
传统方式,将以上3个关注点耦合在一起写。随着业务需求越来越多,导致很难维护。 总结:当一个对象的改变需要同时改变其他对象时,而且还不知道有多少对象有待改变时,应该考虑使用观察者模式。

3)、结构

4)、例子

public abstract class Subject {
private List<Observer> observers = new ArrayList<Observer>();
//增加观察者
public void attach(Observer observer) {
observers.add(observer);
}
//移除观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//通知
public void notify1() {
observers.forEach(o->o.update());
}
}
public abstract class Observer {
public abstract void update();
}
public class ConcreteSubject extends Subject {
private String subjectState; public String getSubjectState() {
return subjectState;
} public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
} }
public class ConcreteObserver extends Observer {
private String name;
private String observerState;
private ConcreteSubject subject; public ConcreteObserver( ConcreteSubject subject,String name) {
this.subject = subject;
this.name = name;
} @Override
public void update() {
observerState = subject.getSubjectState();
System.out.println("观察者"+name+"的新状态是"+observerState);
} public ConcreteSubject getSubject() {
return subject;
} public void setSubject(ConcreteSubject subject) {
this.subject = subject;
}
}
public class Main {
public static void main(String[] args) {
ConcreteSubject s = new ConcreteSubject(); s.attach(new ConcreteObserver(s, "X"));
s.attach(new ConcreteObserver(s, "Y"));
s.attach(new ConcreteObserver(s, "Z")); s.setSubjectState("ABC");
s.notify1(); }
}
--输出
观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC

5)、小结

A、一个事件支持多个订阅者

public static void main(String[] args) {
ConcreteSubject s = new ConcreteSubject();
//多个订阅者
s.attach(new ConcreteObserver(s, "X"));
s.attach(new ConcreteObserver(s, "Y"));
s.attach(new ConcreteObserver(s, "Z"));
//一个事件
s.setSubjectState("ABC");
s.notify1(); }

B、订阅者可动态添加或删除

public abstract class Subject {
private List<Observer> observers = new ArrayList<Observer>();
//增加观察者
public void attach(Observer observer) {
observers.add(observer);
}
//移除观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//通知
public void notify1() {
observers.forEach(o->o.update());
}
}

UML-GoF设计模式的更多相关文章

  1. OOAD-设计模式(二)之GRASP模式与GOF设计模式概述

    一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...

  2. 002-创建型-00-简单工厂【非23种GOF设计模式】

    一.概述 简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实 ...

  3. GOF设计模式特烦恼

    这段时间,学习状态比较一般,空闲时基本都在打游戏,和研究如何打好游戏,终于通过戏命师烬制霸LOL,玩笑了.为了和"学习"之间的友谊小船不翻,决定对以往学习过的GOF设计模式做一个简 ...

  4. 在GoF设计模式

    在GoF设计模式中,结构型模式有: 1.适配器模式 Adapter   适配器模式是将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.   ...

  5. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  6. 8.4 GOF设计模式三: 外观模式 Facade

    GOF设计模式三: 外观模式 Facade  “现有系统”功能强大.复杂,开发“新系统”需要用到其中一部分,但又要增加一部 分新功能,该怎么办?4.1 Facade Pattern: Key Fea ...

  7. 8.3 GOF设计模式二: 适配器模式 Adapter

    GOF设计模式二: 适配器模式 Adapter  为中国市场生产的电器,到了美国,需要有一个转接器才能使用墙上的插座,这个转接 器的功能.原理?复习单实例模式  SingleTon的三个关键点  ...

  8. 8.2 GOF设计模式一: 单实例模式 SingleTon

    GOF设计模式一: 单实例模式 SingleTon  整个美国,只有一个“现任美国总统”  比如,在学校,“老师”,有数百个:“校长”,只有一个  系统运行时,如何保证某个类只允许实例化一个对象 ...

  9. GOF设计模式快速学习

    这段时间,学习状态比较一般,空闲时基本都在打游戏,和研究如何打好游戏,终于通过戏命师烬制霸LOL,玩笑了.为了和"学习"之间的友谊小船不翻,决定对以往学习过的GOF设计模式做一个简 ...

  10. GoF设计模式三作者15年后再谈模式

    Erich Gamma, Richard Helm, 和 Ralph Johnson在GoF设计模式发表15年以后,再谈模式,另外一位作者,也是四色原型的发明者Peter已经过世. 提问者:如今有85 ...

随机推荐

  1. Python 日志模块详解

    前言 我们知道查看日志是开发人员日常获取信息.排查异常.发现问题的最好途径,日志记录中通常会标记有异常产生的原因.发生时间.具体错误行数等信息,这极大的节省了我们的排查时间,无形中提高了编码效率.所以 ...

  2. python基础数据类型--集合(set)

    python基础数据类型--集合(set) 集合是一个数学概念由一个或多个确定的元素所构成的整体叫做集合 集合中的三个特征 1.确定性(元素必须死可hash) 2.互异性(去重) 3.无序性(集合中的 ...

  3. 微信公众号开发之根据OpenID列表群发(十四)

    上一篇我们讲述了<微信公众号开发之根据标签进行群发(十二)>,这次我们讲解一下[根据OpenID列表群发] 根据OpenID列表群发[订阅号不可用,服务号认证后可用] 接口调用请求说明 h ...

  4. Springboot跨域 ajax jsonp请求

    SpringBoot配置: <dependency> <groupId>org.springframework.boot</groupId> <artifac ...

  5. Spring Boot Hello World (restful接口)例子

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  6. python刷LeetCode:28. 实现 strStr()

    难度等级:简单 题目描述: 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 ( ...

  7. java虚拟机之JVM体系结构

    JVM体系结构: 下面重点介绍运行时数据区域模块: (1)java堆(Heap) 被所有线程共享的一块内存区域,在虚拟机启动时创建 用来存储对象实例 可以通过-Xmx和-Xms控制堆的大小 OutOf ...

  8. Arduino - -- 串口双向通信

    需要用到Arduino UNO的串口双向通信功能,以下源码: int val; void setup() {   Serial.begin(9600); // opensserial port, se ...

  9. C语言-逃逸字符、类型转换和布尔类型

    C语言-逃逸字符 逃逸字符是用来表达无法印出来的控制字符或者特殊字符,它由一个反斜杠""开头,后面跟上另一个字符,这两个字符合起来,组成一个字符. \b是backspace,在su ...

  10. ajax 跨域webapi 最简单的demo(只介绍Get)

    这几天遇到一个nodejs的项目,使用VSCode开发,需要连接数据库的,但是用nodejs连接数据库比较繁琐,需要安装很多东西,本人也懒得去研究了.后来想到建一个WebAPI然后用ajax来调用,避 ...