设计模式与代码结构分析

设计模式与代码结构

〇,设计模式简介

  “设计模式”这个概念最早来源于建筑领域,在90年代后被引入软件工程领域。

  软件设计模式,又称设计模式,又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。

一,设计模式要素、原则与分类

  软件设计模式使人们可以更加简单方便地复用成功的设计和体系结构,它通常包含以下几个基本要素:模式名称、别名、动机、问题、解决方案、效果、结构、模式角色、合作关系、实现方法、适用性、已知应用、例程、模式扩展和相关模式等。

  设计模式中还有如下的设计原则:

    开闭原则:对扩展开放,对修改关闭
    里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能
    依赖倒置原则:通过要面向接口的编程来降低类间的耦合性
    单一职责原则:对象(类)不应该承担太多职责
    接口隔离原则:将臃肿庞大的接口拆分成更小的和更具体的接口
    迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
    合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

  1995 年,艾瑞克·伽马(ErichGamma)、理査德·海尔姆(Richard Helm)、拉尔夫·约翰森(Ralph Johnson)、约翰·威利斯迪斯(John Vlissides)等 4 位作者合作出版了《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)一书,其中收录了 23 个设计模式,这是设计模式领域里程碑的事件。直到今天,狭义的设计模式还是本教程中所介绍的 23 种经典设计模式。

  一般来说,这23种设计模式一般又分为三类:创建型模式,行为型模式和机构型模式。

  创建型模式简单来说就是用来创建对象的。一共有五种:单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。

  行为型模式主要是描述类或者对象是怎样交互和怎样分配职责的。一共有十一种:策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

  结构型模式主要是用于处理类或者对象的组合。一共有七种:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

二,观察者模式(Facade模式)简介

1,观察者模式定义

  一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

  简单来说,观察者模式定义对象间的一种一个对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都得到通知并被自动更新。

2,结构与时序

  外观(Facade)模式包含以下主要角色。

  1. 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
  2. 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
  3. 客户(Client)角色:通过一个外观角色访问各个子系统的功能。

3,代码实现

  由于一时没有找到合适的代码示例,再加上熬夜看了巴萨大胜马洛卡有点兴奋,所以直接按照网上的模板实现了一个模拟足球比分推送的观察模式代码。

  首先要做的就是创建观察者和主题的抽象基类。通过纯虚函数规定其派生类所需提供的接口。

 1 // 观察者基类
 2 class Observer_base {
 3 public:
 4     virtual ~Observer_base() {}
 5
 6     // 显示名字
 7     virtual const string get_name() const = 0;
 8
 9     // 更新
10     virtual void update(const string & words) = 0;
11
12     // 重载==运算符,从订阅列表删除元素的时候使用
13     virtual bool operator == (const Observer_base* outer) const = 0;
14 };
15
16
17
18 // 被观察者基类
19 class Target_base{
20 public:
21     virtual ~Target_base() {}
22
23     // 添加订阅者
24     virtual void add_one_follower(Observer_base* outer) = 0;
25
26     // 删除订阅者
27     virtual void rm_one_follower(Observer_base* outer) = 0;
28
29     // 更新发布内容,即本类中的words变量
30     virtual void set_string(const string& words) = 0;
31 };
 1 // 被观察者的一个具体类,比如某队比分推送
 2 class Target_scorePush: public Target_base {
 3 private:
 4     // 观察者集合
 5     set<Observer_base*> followers;
 6
 7     // 被观察者发布的内容
 8     string words;
 9
10 public:
11     // 添加订阅者
12     void add_one_follower(Observer_base* outer) {
13         followers.insert(outer);
14         cout << outer->get_name() << "成功订阅!" << endl;
15     }
16
17     // 删除订阅者
18     void rm_one_follower(Observer_base* outer) {
19         set<Observer_base*>::iterator it;
20         for ( it = followers.begin(); it != followers.end(); ++it) {
21
22             if (**it == outer) {
23                 followers.erase(it);
24                 cout << outer->get_name() << "删除成功!" << endl;
25                 break;
26             }
27
28             cout << outer->get_name() <<"删除失败,预删除用户未在订阅列表中。" << endl;
29         }
30     }
31
32     // 发布新的内容
33     void set_string(const string& words) {
34         // 更新内容
35         this->words = words;
36         cout << "巴萨最新比分推送: " << this->words << endl;
37
38         // 通知订阅者,即调用订阅者的update函数
39         set<Observer_base*>::iterator it;
40         for (it = followers.begin(); it != followers.end(); ++it) {
41             (*it)->update(this->words);
42         }
43
44     }
45 };
46
47
48 // 观察者的一个实例,比如一个球迷
49 class Observer_barcaFans :public Observer_base{
50 private:
51     string name;
52     string news;
53
54 public:
55     // 构造函数
56     Observer_barcaFans(const string& name)
57     :name(name) {}
58
59     // 更新消息
60     void update(const string& words){
61         this->news = words;
62         cout << "用户" << name << "你好! 巴萨的最新比分是: " << news << endl;
63     }
64
65     // 获取球迷名字
66     const string get_name() const {
67         return this->name;
68     }
69
70     // 运算符重载
71     bool operator == (const Observer_base* outer) const {
72         return outer->get_name() == this->name;
73     }
74 };
 1 int main() {
 2     // 创建一个比分推送
 3     Target_base* scorePush_liu = new Target_scorePush();
 4
 5     // 创建两个球迷
 6     Observer_base* li_ming = new Observer_barcaFans("李明");
 7     Observer_base* xiao_hong = new Observer_barcaFans("小红");
 8
 9     // 进行订阅
10     scorePush_liu->add_one_follower(li_ming);
11     scorePush_liu->add_one_follower(xiao_hong);
12
13     // 推送比分
14     scorePush_liu->set_string("巴萨 1 : 0 马洛卡       \n特狮助攻,格子小角度挑射破门!\n");
15     scorePush_liu->set_string("巴萨 2 : 0 马洛卡       \n常规操作,梅西禁区外远射破门。\n");
16     scorePush_liu->set_string("巴萨 2 : 1 马洛卡       \n呵呵。\n");
17     scorePush_liu->set_string("巴萨 3 : 1 马洛卡       \n复制粘贴!梅西禁区外远射破门。\n");
18     scorePush_liu->set_string("巴萨 4 : 1 马洛卡       \n德容直塞,苏神脚跟画彩虹!巧射破门。\n");
19     scorePush_liu->set_string("巴萨 4 : 2 马洛卡       \n呵呵,还敢还手。\n");
20     scorePush_liu->set_string("巴萨 5 : 2 马洛卡       \n苏神回做,梅西搓射洞穿人墙,手捧金球头带帽!\n");
21     scorePush_liu->set_string("全场比赛结束,巴萨 5 : 2 马洛卡       \nps:巴尔韦德下课!\n");
22
23
24     delete scorePush_liu;
25     delete li_ming;
26     delete xiao_hong;
27
28     return 0;
29 }

  代码的实现结果如下:

4,模式分析

  根据“单一职责原则”,在软件中将一个系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统的访问提供了一个简单而单一的入口。 外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度。

   外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。 外观模式的目的在于降低系统的复杂程度。 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能。

  外观模式有如下优点:

  • 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。
  • 实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。
  • 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。
  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。

  同时,外观模式还有如下缺点:

  • 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

5,总结

  在外观模式中,外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

  外观模式包含两个角色:外观角色是在客户端直接调用的角色,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理;在软件系统中可以同时有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能。

  外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。

  外观模式主要优点在于对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易,它实现了子系统与客户之间的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程;其缺点在于不能很好地限制客户使用子系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

  外观模式适用情况包括:要为一个复杂子系统提供一个简单接口;客户程序与多个子系统之间存在很大的依赖性;在层次化结构中,需要定义系统中每一层的入口,使得层与层之间不直接产生联系。

原文地址:https://www.cnblogs.com/imerliu/p/12004973.html

时间: 2024-10-08 10:41:54

设计模式与代码结构分析的相关文章

设计模式与代码重构——ios篇

有一阵子没写技术分享文了,最近每个月写一篇个人空间日记.主要是觉得自己技术比较一般写不出有质量的东西,误人子弟.互联网信息膨胀,让我们获取信息更加便捷,然而获取个人所需的正确信息,却需要每个人具备更强的搜索能力.搜索能力作为代码,就需要更优的算法.算法就像是程序的CPU,决定着程序的运行效率. 与其说电脑改变了世界,不如说是电脑改变了人类改变世界的效率.电脑其实是根据人脑设计的,而程序思想和人的思想相通,所以一个程序员在学会一门语言后,学习第二门语言会来的容易很多,因为编程思想是相通的.我认为,

iOS设计模式(代码分析系列2:简单工厂模式)

简单工厂模式示例代码下载地址, 1.简述 首先需要说明一下,简单工厂模式不属于23种GOF设计模式之一.它也称作静态工作方法模式,是工厂方法模式的特殊实现(也就是说工厂模式包含简单工厂模式).这里对简单工厂模式进行介绍,是为后面的工厂方法和抽象工厂模式做一个引子. 2.定义 "专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类." 世界上就是由一个工厂类,根据传入的参数,动态地决定创建出哪一个产品类的实例. 3.结构图 简要分析结构图: ConcreteProduct

10th.U-boot——代码结构分析(一)

简介 U-Boot(Universal Boot Loader),通用BootLoader,一是可以引导多种操作系统,二是支持多种架构CPU. 教程中是在sourcefoge网站上下载的U-boot-1.1.6源码,进行分析与移植. 结构分析 U-boot-1.1.6有26个子目录,可以简单分为四类: 1.平台相关或开发板相关 2.通用的函数 3.通用的设备驱动程序 4.U-boot工具,示例程序,文档. 目前U-boot-1.1.6支持10种架构.很容易找到与自己板子相似的配置,在上面稍作修改

【JS设计模式】责任链设计模式的代码示例

责任链设计模式: 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任. 责任链模式涉及到的角色如下所示:● 抽象处理者(Handler)角色:定义出一个处理请求的接口.如果需要,接口可以定义 出一个方法以设定和返回对下家的引用.这个角色通常由一个Java抽象类或者Java接口实现.上图中Handle

常见设计模式 (python代码实现)

1.创建型模式 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. 比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息.如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象

案例分析:设计模式与代码的结构特性——工厂方法模式

什么是工厂方法模式 工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦.复用和方便后期维护拓展的目的.它的核心结构有四个角色,分别是抽象工厂:具体工厂:抽象产品:具体产品.工厂方法(Factory Method)模式定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一

requirejs代码结构分析

一.函数入口函数. req = requirejs = function (deps, callback, errback, optional) { //Find the right context, use default var context, config, contextName = defContextName; //“_” //deps 是对象的话,则可能是config. // Determine if have config object in the call. if (!is

jquery源码解析:代码结构分析

本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function(){}; (96,283)   给jQuery对象添加一些属性和方法(实例方法,通过$("div")这类的jQuery实例对象来调用) (285,347)   extend : jQuery的继承方法 (349,817)   jQuery.extend():扩展一些工具方法(静态方法,直接通

Hadoop IPC的代码结构分析

与IPC相关的代码在org.apache.hadoop.ipc包下.共七个文件,其中4个辅助类: RemoteException Status VersionedProtocol ConnectionHeader 主要实现类3个: Client Server RPC 客户端Client: 如上图: 与IPC连接相关的 Client.Connection Client.ConnectionId ConnectionHeader 与远程调用Call相关的 Client.Call Client.Par