眉山市网站建设_网站建设公司_UI设计_seo优化
2026/1/16 22:34:32 网站建设 项目流程

目录

一.专栏简介

二.Jsoncpp库为例子

三.外观模式

四.最少知识原则

五.如何不赢得朋友和影响对象

六.遵守最少知识原则的类

七.外观模式和最少知识原则

八.总结


一.专栏简介

本专栏是我学习《head first》设计模式的笔记。这本书中是用Java语言为基础的,我将用C++语言重写一遍,并且详细讲述其中的设计模式,涉及是什么,为什么,怎么做,自己的心得等等。希望阅读者在读完我的这个专题后,也能在开发中灵活且正确的使用,或者在面对面试官时,能够自信地说自己熟悉常用设计模式。

本章将开始外观模式的学习。

二.Jsoncpp库为例子

Jsoncpp 是一个纯 C++ 编写的开源库,无任何外部依赖,核心作用是:

  1. 解析(反序列化):将 JSON 格式的字符串 / 文件,解析成 C++ 中可直接操作的对象;
  2. 生成(序列化):将 C++ 中的 Jsoncpp 对象,拼接 / 转换为标准的 JSON 格式字符串,也可直接写入文件;
  3. 支持完整的 JSON 语法:键值对、数组、嵌套结构、空值 (null)、各种基础数据类型 (int/double/bool/string)。

它的Json命名空间里的StreamWriterBuilder类CharReaderBuilder类是一个简单工厂,用来创建Json命名空间里的StreamWriterCharReader,它们就可以分别调用writeparse方法来对Json::Value序列化为string字符串和string反序列化为Json::Value对象。

我们不希望我们在使用的时候每次都用这个简单工厂创建一个对象,然后才序列化或者反序列化,这造成代码的重复,麻烦,难以维护。

那么我们就封装了以下这个工具类

class json_util { public: static bool serialize(const Json::Value& root, std::string& str) { Json::StreamWriterBuilder swb; std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter()); std::stringstream ss; int ret = sw->write(root, &ss); if(ret != 0) { ELOG("Json序列化失败"); return false; } str = ss.str(); return true; } static bool unserialize(const std::string& str, Json::Value& root) { Json::CharReaderBuilder crb; std::unique_ptr<Json::CharReader> cr(crb.newCharReader()); std::string err; if(!cr->parse(str.c_str(), str.c_str() + str.size(), &root, &err)) { ELOG("Json反序列化失败,原因:%s" , err.c_str()); return false; } return true; } };

两个工具函数,用于反序列化和反序列化。正如函数参数,我们只关心一个Json::Value可以序列化为一个string或者一个string可以反序列化为一个Json::Value对象,其它的东西我们不关心,所以我们把里面的细节都封装了起来。

三.外观模式

OK!上面的封装就是外观模式的应用。

外观模式为子系统中的一组接口提供了一个统一的接口。外观定义了一个更高级别的接口,使得子系统容易被使用。

外观提供一个简化的接口,但依然暴露系统的全部功能给需要的客户。

外观不仅简化接口,它还把客户从组件的子系统解耦。

外观和适配器的区别:外观和适配器可以包装多个类,但外观的意图是简化,而适配器的意图是转化接口为不同的接口。

下面我们由外观模式引出一个原则:最少知识原则

四.最少知识原则

最少知识原则引导我们减少对象之间的交互,减少到仅发生在一些亲密“朋友”之间。这个原则通常表述如下:

但这到底是什么意思?意思是,当我们设计一个系统时,对于任何对象,都要注意它所交互的类的数量,以及它和这些类如何交互。

这个原则防止我们创建有大量的类在一起的设计,免得系统一部分的变化会连锁影响到其他部分。当你在许多类之间造成许多依赖时,我们的系统就是一个易碎的系统,需要花费许多成本维护,而且复杂得让别人难以理解。

五.如何不赢得朋友和影响对象

该原则提供了一些指南:对于任何对象,从该对象的任何方法,只调用属于以下范围的方法:

  • 对象自身。
  • 作为参数传给方法的对象。
  • 该方法创建或实例化的任何对象。
  • 对象的任何组件。(has-a)

这些指南告诉我们,不要调用从其他方法返回的对象的方法!

调用从另一个调用中返回的对象的方法,有什么坏处呢?好吧,如果我们这样做,相当于向另一个对象的子部分发出请求(而增加我们直接认识的对象数目)。在这种情况下,原则告诉我们,要求该对象为我们做出请求,这样我们就不必知道它的组件对象(保持我们的朋友圈尽可能小)。例如:

不遵守原则:

float getTemp() { Thermometer thermometer = station.getThermometer(); return thermometer.getTemperature(); }

这里,我们从气象站取得温度计(thermometer)对象,然后自行调用getTemperature()方法。

遵守原则:

float getTemp() { return station.getTemperature(); }

当我们应用该原则时,我们给Station(气象站)类添加一个方法,向温度计发出请求。这减少了所依赖的类的数目

六.遵守最少知识原则的类

这是一个Car(汽车)类,展示了我们在调用方法同时依然遵守最少知识原则的所有方式:

class Car { public: Car() { } // 我们可以调用作为参数传递的对象的方法 void start(Key key) { // 这里我们创建了一个新的对象:调用它的方法是合法的 Doors* doors = new Doors(); // 我们可以调用作为参数传递的对象的方法 bool authorized = key.turns(); if(authorized) { // 我们可以调用对象组件的方法 engine.start(); // 我们可以调用对象内的局部方法 updateDashboardDisplay(); // 我们可以调用我们创建或实例化的对象的方法 doors.lock(); } } void updateDashboardDisplay() { // 更新显示 } private: // 这是这个类的一个组件,我们可以调用它的方法 Engine engine; };

七.外观模式和最少知识原则

八.总结

原则不叫法律是有原因的,我们不是必须遵循,而是看实际情况,具体问题具体分析。

虽然最少知识原则减少了对象之间的依赖,研究显示这会减少软件维护成本,应用这个原则也会导致编写更多的“包装者”类来处理对其他组件的方法调用。这会造成复杂度和开发时间增加,运行时性能下降。

下面是一些要点,包含本专栏上一篇博客适配器的:

  • 当你需要使用一个已有的类,而其接口不符合你的需要,就用适配器。
  • 当你需要简化并统一一个大接口,或者一个复杂的接口集,就用外观。
  • 适配器改变接口以符合客户的期望。
  • 外观将客户从一个复杂子系统解耦。
  • 实现一个外观,需要把外观和子系统结合,使用委托来执行外观的工作。
  • 适配器模式有两种形式:对象适配器和类适配器。类适配器需要用到多重继承。
  • 我们可以为一个子系统实现多于一个外观。
  • 适配器包装一个对象以改变其接口,装饰者包装一个对象以添加新的行为和责任,而外观“包装”一群对象以简化其接口。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询