核心提示:一。简单工厂模式首先将需要创建的各种不同对象的相关代码封装到不同的类中,这些类称为具体产品类,而将它们公共的代码进行抽象和提取后封装在一个抽象产品类中,每一个具体产品类都是抽象产品类的子类;然后提供一...
一。简单工厂模式 首先将需要创建的各种不同对象的相关代码封装到不同的类中,这些类称为具体产品类, 而将它们公共的代码进行抽象和提取后封装在一个抽象产品类中,每一个具体产品类都是抽象产品类的子类; 然后提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法, 该方法可以根据所传入的参数不同创建不同的具体产品对象;客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。 简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。 因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式, 它属于类创建型模式。 简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象, 而无须知道其创建细节。简单工厂模式结构比较简单,其核心是工厂类的设计 使用模式的实现方式 ==================================================================================== 软件产品类的实现代码如下: #include <iostream> using namespace std; //抽象软件产品类 class SoftProduct { public: virtual void DisplayProduct() = 0; }; //银行卡产品 class BankCard : public SoftProduct { public: void DisplayProduct() { cout << "项目名称: " << "银行卡识别项目" << endl; } }; //身份证产品 class IdentityCard : public SoftProduct { public: void DisplayProduct() { cout << "项目名称: " << "身份证识别项目" << endl; } }; //驾驶证产品 class DriveLicense : public SoftProduct { public: void DisplayProduct() { cout << "项目名称: " << "驾驶证识别项目" << endl; } }; #endif ====================================================================== 产品工厂的实现代码如下: #ifndef _PRODUCT_FACTORY_H_ #define _PRODUCT_FACTORY_H_ #include <iostream> #include <string> #include "SoftProduct.h" using namespace std; //产品工厂 class ProductFactory { public: //静态方法,根据类型创建具体产品 static SoftProduct * CreateProduct(string strProductName) { SoftProduct * pSoftProduct = NULL; if( 0 == strcmp(strProductName.c_str(), "银行卡识别项目") ) { pSoftProduct = new BankCard(); } else if( 0 == strcmp(strProductName.c_str(), "身份证识别项目") ) { pSoftProduct = new IdentityCard(); } else if( 0 == strcmp(strProductName.c_str(), "驾驶证识别项目") ) { pSoftProduct = new DriveLicense(); } return pSoftProduct; } }; ================================================ 测试程序实现代码如下: #include <iostream> #include "SoftProduct.h" #include "ProductFactory.h" using namespace std; int main() { SoftProduct * pSoftProduct = NULL; //创建银行卡识别项目 pSoftProduct = ProductFactory::CreateProduct("银行卡识别项目"); pSoftProduct->DisplayProduct(); delete pSoftProduct; pSoftProduct = NULL; //创建身份证识别项目 pSoftProduct = ProductFactory::CreateProduct("身份证识别项目"); pSoftProduct->DisplayProduct(); delete pSoftProduct; pSoftProduct = NULL; //创建驾驶证识别项目 pSoftProduct = ProductFactory::CreateProduct("驾驶证识别项目"); pSoftProduct->DisplayProduct(); delete pSoftProduct; pSoftProduct = NULL; return 0; } 添加了一个产品工厂类ProductFactory,该类有一个静态CreateProduct方法,根据参数类型的不同创建不同的具体软件项目产品。 CreateProduct内部封装了具体对象的创建细节,对客户端而言,不再需要具体的对象类型了,客户端完全针对接口进行编程, 对客户端隐藏了对象创建的细节。 简单工厂模式提供了专门的工厂类用于创建对象,将对象的创建和对象的使用分离开,它作为一种最简单的工厂模式在软件开发中得到了较为广泛的应用。 1.主要优点 简单工厂模式的主要优点如下: (1) 工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的职责, 而仅仅“消费”产品,简单工厂模式实现了对象创建和使用的分离。也就是说工厂类封装了变化,封装了对象创建的具体细节, 对客户端隐藏对象创建的细节,使得客户类针对接口进行编程。满足"针对接口编程而不是针对具体编程原则"。 (2) 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名, 通过简单工厂模式可以在一定程度减少使用者的记忆量。满足"迪米特法则,也就是和直接朋友通信原则"。 (3) 具体对象创建是一个变化过程,因此把对象的创建封装起来,体现了"封装变化原则"。 2.主要缺点 简单工厂模式的主要缺点如下: (1) 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响,违背"单一原则"。 (2) 使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度。 (3) 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂, 不利于系统的扩展和维护。违背"开发封闭原则"。 (4) 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结 =====================================设计模式============================================ C++设计模式——工厂方法及工厂方法的隐藏实现 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的产品对象, 而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。工厂方法模式定义如下: 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。 工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),是一种类创建型模式。 Product(抽象产品):它是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的公共父类。 ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。 Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心, 所有创建对象的工厂类都必须实现该接口。 ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。 ========================================================================== QQ空间背景风格的设计与实现 2.1背景风格类 BackgroundStyle背景风格抽象类是抽象的产品类,提供了一个DisplayStyle方法,显示具体的QQ背景风格。 ClassicalStyle古典风格背景类、FashionStyle潮流风格背景类、ArtStyle艺术风格背景类是具体的产品类。 --------------------------------------------------------------------------------- [cpp] view plain copy #ifndef _BACKGROUND_STYLE_H_ #define _BACKGROUND_STYLE_H_ #include <iostream> #include <string> using namespace std; //背景风格抽象类 class BackgroundStyle { public: //虚方法,显示背景风格 virtual void DisplayStyle() = 0; }; //古典风格背景类 class ClassicalStyle : public BackgroundStyle { public: void DisplayStyle() { cout << "古典风格背景" << endl; } }; //潮流风格背景类 class FashionStyle : public BackgroundStyle { public: void DisplayStyle() { cout << "潮流风格背景" << endl; } }; //艺术风格背景类 class ArtStyle : public BackgroundStyle { public: void DisplayStyle() { cout << "艺术风格背景" << endl; } }; #endif --------------------------------------------------------------------------------------- 2.2 背景风格工厂 背景风格工厂类实现代码如下: [cpp] view plain copy #ifndef _STYLE_FACTORY_H_ #define _STYLE_FACTORY_H_ #include "backgroundStyle.h" //背景风格抽象工厂 class StyleFactory { public: //工厂方法,具体背景风格由子类完成创建操作 virtual BackgroundStyle * CreateBackGroundStyle() = 0; }; //古典风格工厂 class ClassicalStyleFactory : public StyleFactory { public: BackgroundStyle * CreateBackGroundStyle() { BackgroundStyle * pClassicalStyle = new ClassicalStyle(); return pClassicalStyle; } }; //潮流风格工厂 class FashionStyleFactory : public StyleFactory { public: BackgroundStyle * CreateBackGroundStyle() { BackgroundStyle * pFashionStyle = new FashionStyle(); return pFashionStyle; } }; //艺术风格工厂 class ArtStyleFactory : public StyleFactory { public: BackgroundStyle * CreateBackGroundStyle() { BackgroundStyle * pArtStyle = new ArtStyle(); return pArtStyle; } }; #endif --------------------------------------------------------------------- 4.1. 主要优点 工厂方法模式的主要优点如下: (1) 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节, 用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。也就是说工厂方法模式封装了变化, 封装了对象创建的具体细节,符合"封装变化原则"。 (2) 每一个具体工厂只负责创建一个对应的产品,符合"单一原则"。 (3) 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端, 也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好, 完全符合“开闭原则”。 (4)客户端只需要认识抽象的产品类,无需认识具体产品类,降低了客户端和具体产品类的耦合度。 也就是说客户端针对接口进行编程,符合"针对接口进行编程而不是针对具体进行编程原则"。 4.2. 主要缺点 工厂方法模式的主要缺点如下: (1) 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类, 系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。 =====================================设计模式============================================ C++设计模式--抽象工厂模式 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形式。抽象工厂模式与工厂方法模式最大的区别在于, 工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构, 一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。 当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率 抽象工厂模式为创建一组对象提供了一种解决方案。 与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。抽象工厂模式定义如下: 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。它是一种对象创建型模式。 AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的工厂方法,每一个工厂方法对应一种产品。 这些产品可以没有任何的联系,但这些产品可以组合起来,可以构成一个产品族。 ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的工厂方法,生成一组具体产品, 这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。 AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。 ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。 5、抽象工厂模式总结 简单工厂模式和工厂方法模式都只产生一种类型的产品对象。然而在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品, 这些产品可以没有任何的联系,位于不同的产品等级,但这些产品可以组合起来,构成一个产品族。抽象工厂模式是工厂方法模式的进一步延伸, 由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用。使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。 5.1.主要优点 抽象工厂模式的主要优点如下: (1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易, 所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。 抽象工厂封装了变化,封装了对象创建的具体细节,对客户端隐藏对象创建的具体细节,符合"封装变化原则"。 (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。 (3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。 (4) 客户端可以针对抽象进行编程,而不需要知道具体类型,符合"针对接口进行编程而不是针对具体进行编程原则"。 5.2.主要缺点 抽象工厂模式的主要缺点如下: 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则 =====================================设计模式============================================ C++设计模式——建造者模式 建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。 Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法, 一类方法是buildPartX(),它们用于创建复杂对象的各个部件; 另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。 ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象, 也可以提供一个方法返回创建好的复杂产品对象。 Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。 Director(指挥者):指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系, 可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。 客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象, 然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。 播放器 -------------------------------------------------------------------------------------------------- 暴风影音播放器.h头文件代码如下:------------具体建造者 [cpp] view plain copy <pre name="code" class="cpp">#ifndef _PLAYER_H_ #define _PLAYER_H_ #include <iostream> #include <string> using namespace std; //播放器 class Player { private: string m_strMenu; //菜单栏 string m_strWindow; //主窗口 string m_strPlayList; //播放列表 string m_strControlBar; //进度条 string m_strCollectList; //收藏列表 public: //设置部件 void SetMenu(string strMenu); void SetWindow(string strWindow); void SetPlayList(string strPlayList); void SetControlBar(string strControlBar); void SetCollectList(string strCollectList); //获取各部件 string GetMenu(); string GetWindow(); string GetPlayList(); string GetControlBar(); string GetCollectList(); //显示播放器窗口包含的部件 void Display(); }; #endif ---------------------------------------------------------------------------- 暴风影响播放器Cpp文件代码如下: [cpp] view plain copy #include "Player.h" //设置主菜单部件 void Player::SetMenu(string strMenu) { m_strMenu = strMenu; } //设置主窗口部件 void Player::SetWindow(string strWindow) { m_strWindow = strWindow; } //设计播放列表部件 void Player::SetPlayList(string strPlayList) { m_strPlayList = strPlayList; } //设置滚动条部件 void Player::SetControlBar(string strControlBar) { m_strControlBar = strControlBar; } //设置收藏列表部件 void Player::SetCollectList(string strCollectList) { m_strCollectList = strCollectList; } //获取主菜单部件 string Player::GetMenu() { return m_strMenu; } //获取主窗口部件 string Player::GetWindow() { return m_strWindow; } //获取播放列表部件 string Player::GetPlayList() { return m_strPlayList; } //获取滚动条部件 string Player::GetControlBar() { return m_strControlBar; } //获取收藏列表部件 string Player::GetCollectList() { return m_strCollectList; } //显示播放器窗口包含的部件 void Player::Display() { cout << "---" << m_strWindow << endl; cout << "---" << m_strMenu << endl; cout << "---" << m_strPlayList << endl; cout << "---" << m_strControlBar << endl; cout << "---" << m_strCollectList << endl << endl; }