C++设计模式
# 创建型模型
# 简单工厂模式 不属于GoF设计模式
- 工厂(Factory)角色:简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
- 抽象产品(Abstract Product)角色:简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product)角色:简单工厂模式所创建的具体实例对象。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
//抽象水果
class Fruit{
public:
virtual void shoName() = 0;
};
//苹果类
class Apple : public Fruit{
public:
virtual void shoName(){
cout << "我是苹果" << endl;
}
};
//香蕉类
class Banana : public Fruit{
public:
virtual void shoName(){
cout << "我是香蕉" << endl;
}
};
//鸭梨类
class Pear : public Fruit{
public:
virtual void shoName(){
cout << "我是鸭梨" << endl;
}
};
//水果工厂
class FruitFactory{
public:
static Fruit* CreateFruit(string name){
if (name.compare("apple") == 0){
return new Apple; }
else if (name.compare("banana") == 0){
return new Banana; }
else if (name.compare("pear") == 0){
return new Pear; } }
};
//测试
void test01(){
Fruit* fruit = NULL;
fruit = FruitFactory::CreateFruit("apple"); //工厂生产苹果
fruit->shoName();
delete fruit;
fruit = FruitFactory::CreateFruit("banana"); //工厂生产香蕉
fruit->shoName();
delete fruit;
fruit = FruitFactory::CreateFruit("pear"); //工厂生产鸭梨
fruit->shoName();
delete fruit;
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS;
}
# 简单工厂模式的优缺点
优点:
(1)实现了对象创建和使用的分离。
(2)不需要记住具体类名,记住参数即可,减少使用者记忆量。
缺点:
(1)对工厂类职责过重,一旦不能工作,系统受到影响。
(2)增加系统中类的个数,复杂度和理解度增加。
(3)违反“开闭原则”,添加新产品需要修改工厂逻辑,工厂越来越复杂。
# 工厂方法模式
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
- 抽象工厂(Abstract Factory)角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。
- 工厂(Concrete Factory)角色:具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
- 抽象产品(Abstract Product)角色:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product)角色:工厂方法模式所创建的具体实例对象。
- 简单工厂模式 + “开闭原则” = 工厂方法模式
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//抽象水果
class AbstractFruit{
public:
virtual void showName() = 0;
};
/* 具体水果 start */
//苹果
class Apple : public AbstractFruit{
public:
virtual void showName(){
cout << "我是苹果" << endl;
}
};
//香蕉
class Banana : public AbstractFruit{
public:
virtual void showName(){
cout << "我是香蕉" << endl;
}
};
//鸭梨
class Pear : public AbstractFruit{
public:
virtual void showName(){
cout << "我是鸭梨" << endl;
}
};
/* 具体水果 end */
//抽象工厂
class AbstractFactory{
public:
virtual AbstractFruit* CreateFruit() = 0;
};
/* 具体工厂类 start */
//苹果工厂
class AppleFactory : public AbstractFactory{
public:
virtual AbstractFruit* CreateFruit(){
return new Apple; }
};
//香蕉工厂
class BananaFactory : public AbstractFactory{
public:
virtual AbstractFruit* CreateFruit(){
return new Banana; }
};
//鸭梨工厂
class PearFactory : public AbstractFactory{
public:
virtual AbstractFruit* CreateFruit(){
return new Pear; }
};
/* 具体工厂类 end */
//测试
void test01(){
AbstractFactory* factory = NULL;
AbstractFruit* fruit = NULL;
factory = new AppleFactory; //创建苹果工厂
fruit = factory->CreateFruit(); //苹果工厂生产苹果
fruit->showName();
factory = new BananaFactory; //创建香蕉工厂
fruit = factory->CreateFruit(); //香蕉工厂生产苹果
fruit->showName();
factory = new PearFactory; //创建鸭梨工厂
fruit = factory->CreateFruit(); //鸭梨工厂生产苹果
fruit->showName();
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS; }
# 简单描述
- 给我来一个香蕉工厂
- 给我来一个水果
- 香蕉生产器只能生产具体的香蕉。
# 工厂方法模式的优缺点
优点:
(1)不需要记住具体类名,甚至连具体参数都不用记忆。
(2)实现了对象创建和使用的分离。
(3)系统的可扩展性也就变得非常好,无需修改接口和原类。
缺点:
(1)增加系统中类的个数,复杂度和理解度增加。
(2)增加了系统的抽象性和理解难度。
# 抽象工厂模式
工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族,由同一个工厂来统一生产,这就是我们本文将要学习的抽象工厂模式的基本思想。
- 抽象工厂(Abstract Factory)角色:它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
- 具体工厂(Concrete Factory)角色:它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
- 抽象产品(Abstract Product)角色:它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。
- 具体产品(Concrete Product)角色:它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//抽象苹果类
class AbstractApple{
public:
virtual void showName() = 0;
};
//抽象香蕉
class AbstractBanana{
public:
virtual void showName() = 0;
};
//抽象鸭梨
class AbstractPear{
public:
virtual void showName() = 0;
};
//中国苹果
class ChineseApple : public AbstractApple{
public:
virtual void showName(){
cout << "中国苹果" << endl;
}
};
//美国苹果
class AmericanApple : public AbstractApple{
public:
virtual void showName(){
cout << "美国苹果" << endl;
}
};
//日本苹果
class JapaneseApple : public AbstractApple{
public:
virtual void showName(){
cout << "日本苹果" << endl;
}
};
//中国香蕉
class ChineseBanana : public AbstractBanana{
public:
virtual void showName(){
cout << "中国香蕉" << endl;
}
};
//美国香蕉
class AmericanBanana : public AbstractBanana{
public:
virtual void showName(){
cout << "美国香蕉" << endl;
}
};
//日本香蕉
class JapaneseBanana : public AbstractBanana{
public:
virtual void showName(){
cout << "日本香蕉" << endl;
}
};
//中国鸭梨
class ChinesePear : public AbstractPear{
public:
virtual void showName(){
cout << "中国鸭梨" << endl;
}
};
//美国鸭梨
class AmericanPear : public AbstractPear{
public:
virtual void showName(){
cout << "美国鸭梨" << endl;
}
};
//日本鸭梨
class JapanesePear : public AbstractPear{
public:
virtual void showName(){
cout << "日本鸭梨" << endl;
}
};
//抽象工厂
class AbstractFactory{
public:
virtual AbstractApple* CreateApple() = 0;
virtual AbstractBanana* CreateBanana() = 0;
virtual AbstractPear* CreatePear() = 0;
};
//中国工厂
class ChineseFactory : public AbstractFactory{
public:
virtual AbstractApple* CreateApple(){
return new ChineseApple; }
virtual AbstractBanana* CreateBanana(){
return new ChineseBanana; }
virtual AbstractPear* CreatePear(){
return new ChinesePear; }
};
//美国工厂
class AmericanFactory : public AbstractFactory{
public:
virtual AbstractApple* CreateApple(){
return new AmericanApple; }
virtual AbstractBanana* CreateBanana(){
return new AmericanBanana; }
virtual AbstractPear* CreatePear(){
return new AmericanPear; }
};
//美国工厂
class JapaneseFactory : public AbstractFactory{
public:
virtual AbstractApple* CreateApple(){
return new JapaneseApple;
}
virtual AbstractBanana* CreateBanana(){
return new JapaneseBanana; }
virtual AbstractPear* CreatePear(){
return new JapanesePear; }
};
void test01(){
AbstractFactory* factory = NULL;
AbstractApple* apple = NULL;
AbstractBanana* banana = NULL;
AbstractPear* pear = NULL;
factory = new ChineseFactory; //创建中国工厂
apple = factory->CreateApple();
banana = factory->CreateBanana();
pear = factory->CreatePear();
apple->showName();
banana->showName();
pear->showName();
delete pear;
delete banana;
delete apple;
delete factory;
factory = new AmericanFactory; //创建美国工厂
apple = factory->CreateApple();
banana = factory->CreateBanana();
pear = factory->CreatePear();
apple->showName();
banana->showName();
pear->showName();
delete pear;
delete banana;
delete apple;
delete factory;
factory = new JapaneseFactory; //创建日本工厂
apple = factory->CreateApple();
banana = factory->CreateBanana();
pear = factory->CreatePear();
apple->showName();
banana->showName();
pear->showName();
delete pear;
delete banana;
delete apple;
delete factory;
}
int main(){
test01();
system("pause");
return EXIT_SUCCESS; }
# 简单描述
- 给来一个美国的工厂
- 再给我来一个鸭梨
# 抽象工厂模式的优缺点
优点:
(1)拥有工厂方法模式的优点
(2)当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
(3)增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。
# 单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
Singleton(单例):在单例类的内部实现只生成一个实例,同时它提供一个静态的 getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个 Singleton类型的静态对象,作为外部共享的唯一实例。
如何构建单例:
一是单例模式的类只提供私有的构造函数,
二是类定义中含有一个该类的静态私有对象,
三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
# 懒汉式
class Singleton_lazy{
private:
Singleton_lazy(){}
public:
static Singleton_lazy* getInstance(){
if (pSingleton == NULL){
pSingleton = new Singleton_lazy;
}
return pSingleton;
}
private:
static Singleton_lazy* pSingleton;
};
//类外初始化
Singleton_lazy* Singleton_lazy::pSingleton = NULL;
# 饿汉式
class Singleton_hungry{
private:
Singleton_hungry(){}
public:
static Singleton_hungry* getInstance(){
return pSingleton;
}
class Garbo{
~Garbo(){
if (pSingleton != NULL){
delete pSingleton;
}
}
};
private:
static Singleton_hungry* pSingleton;
static Garbo garbo;
};
Singleton_hungry* Singleton_hungry::pSingleton = new Singleton_hungry;
# 单例模式的优缺点
优点:
(1)单例模式提供了对唯一实例的受控访问。
(2)节约系统资源。由于在系统内存中只存在一个对象。
缺点:
(1) 扩展略难。单例模式中没有抽象层。
(2) 单例类的职责过重。
# 结构型模式
# 观察者模式
观察者模式又叫发布-订阅模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象。
Subject(被观察对象) addObserver, deleteObserver, Notify(dispatcher)
ConcreteSubject(具体的被观察对象)
Observer(观察者) handlerData
ConcreteObserver(具体的观察者)