面向对象设计原则
背案例而不是背原则,主打一个高内聚,低耦合。
开闭原则
对拓展开放,对修改关闭,增加功能是通过增加代码实现的,而不是去修改源代码
#include <iostream>
//写一个抽象类
class AbstractCalculator{
public:
virtual int getResult() = 0;
virtual void setOperatorNumber(int a,int b) = 0;
};
//加法器类
class PlusCalculator:public AbstractCalculator{
public:
int m_A;
int m_B;
void setOperatorNumber(int a,int b){
this->m_A=a;
this->m_B=b;
}
int getResult(){
return m_A+m_B;
}
};
//减法器类
class SubstractCalculator:public AbstractCalculator{
public:
int m_A;
int m_B;
void setOperatorNumber(int a,int b){
this->m_A=a;
this->m_B=b;
}
int getResult(){
return m_A-m_B;
}
};
//乘法器类
class MultiplyCalculator:public AbstractCalculator{
public:
int m_A;
int m_B;
void setOperatorNumber(int a,int b){
this->m_A=a;
this->m_B=b;
}
int getResult(){
return m_A*m_B;
}
};
void test01(){
PlusCalculator pc;
pc.setOperatorNumber(10,20);
std::cout << "result: " << pc.getResult() << std::endl;
}
int main(){
test01();
}
迪米特法则
又叫最少知识原则,尽量保留不暴露过多的数据。比如,我只想要品质信息,那你就专门弄一个关于品质的中介,而不是我直接去访问所有的实例。最小暴露原则。
#include <iostream>
#include <string>
#include <vector>
//迪米特原则:又叫最少知识原则,尽量保留不暴露过多的数据
//我只想要品质信息,那你就专门弄一个关于品质的中介,而不是我直接去访问所有的实例
class AbstractBuilding {
public:
virtual void sale() = 0;
virtual std::string getQuality() = 0;
};
//楼盘A
class BuildingA : public AbstractBuilding {
public:
std::string m_Quality;
BuildingA() {
m_Quality = "高品质";
}
void sale() {
std::cout << "楼盘A" << m_Quality << "被售卖" << std::endl;
return;
}
std::string getQuality(){
return m_Quality;
}
};
//楼盘B
class BuildingB : public AbstractBuilding {
public:
std::string m_Quality;
BuildingB() {
m_Quality = "低品质";
}
void sale() {
std::cout << "楼盘B" << m_Quality << "被售卖" << std::endl;
return;
}
std::string getQuality(){
return m_Quality;
}
};
//直接暴露实例
void test01() {
BuildingA ba;
if (ba.m_Quality == "低品质") {
ba.sale();
}
BuildingB bb;
if (bb.m_Quality == "低品质") {
bb.sale();
}
}
//中介类
class Mediator {
public:
std::vector<AbstractBuilding *> vBuilding;
Mediator() {
AbstractBuilding *building = new BuildingA;
vBuilding.push_back(building);
building = new BuildingB;
vBuilding.push_back(building);
}
~Mediator() {
for (std::vector<AbstractBuilding *>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
if (*it != NULL) {
delete *it;
}
}
}
//对外提供接口
AbstractBuilding *fingMyBuilding(std::string quality) {
for (std::vector<AbstractBuilding *>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
if ((*it)->getQuality()==quality) {
return *it;
}
}
return nullptr;
}
};
//通过中介类获取信息
void test02(){
Mediator mediator;
AbstractBuilding* building =mediator.fingMyBuilding("高品质");
if(building!=NULL){
building->sale();
}else{
std::cout << "没有符合您条件的楼盘" << std::endl;
}
}
int main() {
test01();
test02();
return 0;
}
合成复用原则
泛化(继承) 和 组合 优先使用组合,简称少用继承
// 泛化(继承) 和 组合 优先使用组合,简称少用继承
#include <iostream>
class AbstractCar{
public:
virtual void run()=0;
};
//大众
class Dazhong:public AbstractCar{
public:
void run(){
std::cout << "大众,启动" << std::endl;
}
};
//拖拉机
class Tuolaji:public AbstractCar{
public:
void run(){
std::cout << "拖拉机,启动" << std::endl;
}
};
//使用泛化关系
#if 0
//这样每次都要换车
class Person:public Tuolaji{
public:
void Doufeng(){
run();
}
};
class PersonB:public Dazhong{
public:
void Doufeng(){
run();
}
};
#endif
//使用组合
class Person{
public:
AbstractCar *car;
void setCat(AbstractCar* car){
this->car=car;
}
void Doufeng(){
car->run();
if(car!=NULL){
delete car;
}
}
};
void test01(){
Person p;
p.setCat(new Dazhong);
p.Doufeng();
p.setCat(new Tuolaji);
p.Doufeng();
}
int main(){
test01();
}
依赖倒转原则
依赖不要用具体实现,而要用抽象类,保证拓展性
//依赖不要用具体实现,而要用抽象类,保证拓展性
#include <iostream>
class AbstractWorker {
public:
virtual void doBusiness() = 0;
};
//这里运用了开闭原则,模仿计算器案例进行实现
//专门办理存款业务的工作人员
class SaveBankWorker: public AbstractWorker{
public:
void doBusiness(){
std::cout << "办理存款业务" << std::endl;
}
};
//专门办理支付业务的工作人员
class PayBankWorker: public AbstractWorker{
public:
void doBusiness(){
std::cout << "办理支付业务" << std::endl;
}
};
//专门办理转账业务的工作人员
class TransferWorker:public AbstractWorker{
public:
void doBusiness(){
std::cout << "办理转账业务" << std::endl;
}
};
//中层模块
void doNewBusiness(AbstractWorker* worker){
worker->doBusiness();
if(worker!= nullptr){
delete worker;
}
}
//业务模块
void test01(){
doNewBusiness(new TransferWorker);
doNewBusiness(new SaveBankWorker);
}
int main(){
test01();
}
常用的设计模式
工厂模式
简单工厂模式
不要直接去创建类,而是通过和工厂交互,让工厂生产,使得我不需要知道创建细节
但是简单工厂添加新的水果时明显不符合开闭原则
#include <iostream>
class AbstractFruit{
public:
virtual void showName() = 0;
};
class Apple:public AbstractFruit{
public:
void showName(){
std::cout << "我是苹果" << std::endl;
}
};
class Pear:public AbstractFruit{
public:
void showName(){
std::cout << "我是梨" << std::endl;
}
};
class Banana:public AbstractFruit{
void showName(){
std::cout << "我是香蕉" << std::endl;
}
};
class FruitFactory{
public:
static AbstractFruit* createFruit(std::string flag){
if(flag=="apple"){
return new Apple;
}else if(flag=="banana"){
return new Banana;
}else if(flag=="pear"){
return new Pear;
}else{
return NULL;
}
}
};
void test01(){
FruitFactory* factory = new FruitFactory;
AbstractFruit* fruit = factory->createFruit("apple");
fruit->showName();
delete fruit;
fruit = factory->createFruit("pear");
fruit->showName();
delete fruit;
fruit = factory->createFruit("banana");
fruit->showName();
delete fruit;
}
int main(){
test01();
}
工厂方法模式
简单工厂的工厂不符合开闭原则,把工厂符合开闭原则就是工厂方法模式
唯一优点:符合开闭
缺点:类太多,一个水果一个工厂
#include <iostream>
class AbstractFruit{
public:
virtual void showName() = 0 ;
};
class Apple:public AbstractFruit{
void showName(){
std::cout << "我是苹果!" << std::endl;
}
};
class Pear:public AbstractFruit{
void showName(){
std::cout << "我是梨!" << std::endl;
}
};
class Banana:public AbstractFruit{
void showName(){
std::cout << "我是香蕉!" << std::endl;
}
};
class AbstractFruitFactory{
public:
virtual AbstractFruit* createFruit()=0;
};
//苹果工厂
class AppleFactory:public AbstractFruitFactory{
AbstractFruit* createFruit(){
return new Apple;
}
};
//香蕉工厂
class BananaFactory:public AbstractFruitFactory{
AbstractFruit* createFruit(){
return new Banana;
}
};
//梨工厂
class PearFactory:public AbstractFruitFactory{
AbstractFruit* createFruit(){
return new Pear;
}
};
void test01(){
AbstractFruitFactory* factory=NULL;
AbstractFruit* fruit=NULL;
factory=new AppleFactory;
fruit=factory->createFruit();
fruit->showName();
delete factory;
delete fruit;
factory=new PearFactory;
fruit=factory->createFruit();
fruit->showName();
delete factory;
delete fruit;
factory=new BananaFactory;
fruit=factory->createFruit();
fruit->showName();
delete factory;
delete fruit;
}
int main(){
test01();
}
抽象工厂模式
抽象工厂模式相当于对简单工厂进行抽象
添加产品族符合开闭原则,添加产品等级结构不符合开闭原则
产品族和产品等级结构
- 产品组:横着的一行,同一产地或者统一厂商,功能不同
- 产品等级:竖着的一列,功能相同,产地或者产商不同
#include <iostream>
class AbstractFruit{
public:
virtual void showName() = 0;
};
class ChinaApple:public AbstractFruit{
public:
void showName(){
std::cout << "我是中国苹果" << std::endl;
}
};
class ChinaBanana:public AbstractFruit{
public:
void showName(){
std::cout << "我是中国香蕉" << std::endl;
}
};
class ChinaPear:public AbstractFruit{
public:
void showName(){
std::cout << "我是中国梨" << std::endl;
}
};
class USAApple:public AbstractFruit{
public:
void showName(){
std::cout << "我是美国苹果" << std::endl;
}
};
class USABanana:public AbstractFruit{
public:
void showName(){
std::cout << "我是美国香蕉" << std::endl;
}
};
class USAPear:public AbstractFruit{
public:
void showName(){
std::cout << "我是美国梨" << std::endl;
}
};
class JapanApple:public AbstractFruit{
public:
void showName(){
std::cout << "我是日本苹果" << std::endl;
}
};
class JapanBanana:public AbstractFruit{
public:
void showName(){
std::cout << "我是日本香蕉" << std::endl;
}
};
class JapanPear:public AbstractFruit{
public:
void showName(){
std::cout << "我是美国日本梨" << std::endl;
}
};
class AbstractFruitFactory{
public:
virtual AbstractFruit* createApple()=0;
virtual AbstractFruit* createBanana()=0;
virtual AbstractFruit* createPear()=0;
};
class ChinaFruitFactory:public AbstractFruitFactory{
public:
AbstractFruit* createApple() {
return new ChinaApple;
}
AbstractFruit* createBanana(){
return new ChinaBanana;
}
AbstractFruit* createPear(){
return new ChinaPear;
}
};
class USAFruitFactory:public AbstractFruitFactory{
AbstractFruit* createApple() {
return new USAApple;
}
AbstractFruit* createBanana(){
return new USABanana;
}
AbstractFruit* createPear(){
return new USAPear;
}
};
class JapanFruitFactory:public AbstractFruitFactory{
AbstractFruit* createApple() {
return new JapanApple;
}
AbstractFruit* createBanana(){
return new JapanBanana;
}
AbstractFruit* createPear(){
return new JapanPear;
}
};
void test01(){
AbstractFruitFactory* fruitFactory=NULL;
AbstractFruit* apple=NULL;
AbstractFruit* banana=NULL;
AbstractFruit* pear=NULL;
fruitFactory=new ChinaFruitFactory;
apple=fruitFactory->createApple();
banana=fruitFactory->createBanana();
pear=fruitFactory->createBanana();
apple->showName();
banana->showName();
pear->showName();
delete fruitFactory;
delete apple;
delete banana;
delete pear;
}
int main(){
test01();
}
单例模式
保证一个类只有一个实例,比如你只需要一个管理者。你只需要搞一个全局共享的实例,只能通过规定的方式创建,而不能随意创建。
单例模式的一般步骤
- 私有化构造函数(不能随意创建)
- 私有化静态变量指针
- 公有化静态接口,可以让用户获得单粒对象
#include <iostream>
//单例模式的一般思路
class A{
private:
static A* a;
A(){}
public:
static A* getInstance(){
return a;
}
};
A* A::a=new A;
//饿汉式和懒汉式
//两者的区别在于对象创建时机
//懒汉式,要使用的时候才创建,线程不安全
class Singleton_lazy{
private:
static Singleton_lazy* singletonLazy;
Singleton_lazy(){
std::cout << "懒汉式执行" << std::endl;
};
public:
static Singleton_lazy* getInstance(){
if(singletonLazy== nullptr){
singletonLazy=new Singleton_lazy;
}
return singletonLazy;
}
};
Singleton_lazy* Singleton_lazy::singletonLazy= nullptr;
//饿汉式,早于主函数执行之前就创建好了,线程安全
class Singleton_hungry{
private:
static Singleton_hungry* singletonHungry;
Singleton_hungry(){
std::cout << "饿汉式创建" << std::endl;
};
public:
static Singleton_hungry* getInstance(){
return singletonHungry;
}
};
Singleton_hungry* Singleton_hungry::singletonHungry=new Singleton_hungry;
void test01(){
//验证饿汉式和懒汉式的创建时机
Singleton_lazy* p=Singleton_lazy::getInstance();
}
void test02(){
//验证是否真的是唯一单例
Singleton_lazy* p1=Singleton_lazy::getInstance();
Singleton_lazy* p2=Singleton_lazy::getInstance();
if(p1==p2){
std::cout << "唯一单例" << std::endl;
}
}
int main(){
std::cout << "主函数执行" << std::endl;
test01();
test02();
}
代理模式
提供一种代理来看控制对其他对象的访问
#include <iostream>
//代理就是在系统之上再加一层 -> 代理 = 系统 + 一些东西 -> 代理包含系统
//你可以直接理解为代理就是系统
//基于这个原理,那么代理和系统必须具有相同的接口
class AbstractCommonInterface{
public:
virtual void run()=0;
};
//必须要有权限验证,而不是所有人都能访问我的系统,必须提供用户名和密码
class MySystem:public AbstractCommonInterface{
public:
void run(){
std::cout << "系统启动" << std::endl;
}
};
class MySystemProxy:public AbstractCommonInterface{
public:
MySystemProxy(std::string userName,std::string password){
this->userName=userName;
this->password=password;
pMySystem=new MySystem;
}
void run(){
if(userName=="admin" && password=="admin"){
pMySystem->run();
}else{
std::cout << "系统权限不足" << std::endl;
}
}
~MySystemProxy(){
if(pMySystem!= nullptr){
delete pMySystem;
}
}
private:
std::string userName;
std::string password;
MySystem* pMySystem;
};
void test01(){
MySystemProxy* proxy=nullptr;
proxy=new MySystemProxy("root","admin");
proxy->run();
delete proxy;
proxy=new MySystemProxy("admin","admin");
proxy->run();
delete proxy;
}
int main(){
test01();
}
外观模式
满足迪米特原则,也就是最小暴露原则,你暴露一个接口让我直接实现想要的功能就行,我不想知道里面有什么东西
#include <iostream>
class Television{
public:
void On(){
std::cout << "电视机打开..." << std::endl;
}
void Off(){
std::cout << "电视机关闭..." << std::endl;
}
};
class Light{
public:
void On(){
std::cout << "灯打开..." << std::endl;
}
void Off(){
std::cout << "灯关闭..." << std::endl;
}
};
class Audio{
public:
void On(){
std::cout << "音箱打开..." << std::endl;
}
void Off(){
std::cout << "音箱关闭..." << std::endl;
}
};
class Microphone{
public:
void On(){
std::cout << "麦克风打开..." << std::endl;
}
void Off(){
std::cout << "麦克风关闭..." << std::endl;
}
};
class DVDPlayer{
public:
void On(){
std::cout << "DVD播放器打开..." << std::endl;
}
void Off(){
std::cout << "DVD播放器关闭..." << std::endl;
}
};
class GamePlayer{
public:
void On(){
std::cout << "游戏机打开..." << std::endl;
}
void Off(){
std::cout << "游戏机关闭..." << std::endl;
}
};
class KTVMode{
public:
Television* pTV;
Light* pLight;
Audio* pAudio;
Microphone* pMicrophone;
DVDPlayer* pDvdPlayer;
KTVMode(){
pTV=new Television;
pLight=new Light;
pAudio=new Audio;
pMicrophone=new Microphone;
pDvdPlayer=new DVDPlayer;
}
~KTVMode(){
delete pDvdPlayer;
delete pMicrophone;
delete pAudio;
delete pLight;
delete pTV;
}
void onKTVMode(){
pTV->On();
pLight->On();
pAudio->On();
pMicrophone->On();
pDvdPlayer->On();
}
void offKTVMode(){
pTV->Off();
pLight->Off();
pAudio->Off();
pMicrophone->Off();
pDvdPlayer->Off();
}
};
适配器模式
不如叫转接口模式
比如将 双参数函数 转接为 单参数函数
思路:双参数函数 封装成 单参数函数,然后内部一个参数固定
#include <iostream>
#include <vector>
#include <algorithm>
class MyPrint{
public:
int operator()(int a,int b){
return a+b;
}
};
class Adapter{
public:
MyPrint myPrint;
int param;
Adapter(int param){
this->param=param;
}
int operator()(int v){
return myPrint(v,param);
}
};
Adapter MyBind2nd(int a){
return Adapter(a);
}
int main(){
std::vector<int> v;
for(int i=0;i<10;i++){
v.push_back(i);
}
Adapter adapter= MyBind2nd(20);
std::for_each(v.begin(),v.end(),adapter);
}
模版方法模式
步骤相同,只是每个步骤需要特定的实现
#include <iostream>
class DrinkTemplate{
public:
//煮水
virtual void boilWater()=0;
//冲泡
virtual void brew()=0;
//倒入杯中
virtual void pourInCup()=0;
//加辅料
virtual void addSomething()=0;
//模版方法
void make(){
boilWater();
brew();
pourInCup();
addSomething();
}
};
//冲泡咖啡
class Coffee:public DrinkTemplate{
public:
//煮水
virtual void boilWater(){
std::cout << "煮山泉水" << std::endl;
};
//冲泡
virtual void brew(){
std::cout << "冲泡咖啡" << std::endl;
};
//倒入杯中
virtual void pourInCup(){
std::cout << "咖啡倒入杯中" << std::endl;
};
//加辅料
virtual void addSomething(){
std::cout << "加入牛奶" << std::endl;
};
};
//冲泡茶
class Tea:public DrinkTemplate{
public:
//煮水
virtual void boilWater(){
std::cout << "煮自来水" << std::endl;
};
//冲泡
virtual void brew(){
std::cout << "冲泡铁观音" << std::endl;
};
//倒入杯中
virtual void pourInCup(){
std::cout << "茶水倒入杯中" << std::endl;
};
//加辅料
virtual void addSomething(){
std::cout << "加入柠檬" << std::endl;
};
};
void test01(){
Tea* tea=new Tea;
tea->make();
Coffee* coffee=new Coffee;
coffee->make();
}
int main(){
test01();
}
策略模式
封装特定方法
//都拥有使用武器这一方法,那就封装一个武器策略
#include <iostream>
//也可以理解为抽象武器
class WeaponStrategy{
public:
virtual void UseWeapon()= 0;
};
class AK47:public WeaponStrategy{
public:
void UseWeapon(){
std::cout << "使用AK47" << std::endl;
}
};
class Knife:public WeaponStrategy{
public:
void UseWeapon(){
std::cout << "使用匕首" << std::endl;
}
};
class Character{
public:
WeaponStrategy* pWeapon;
void setWeapon(WeaponStrategy* weaponStrategy){
this->pWeapon=weaponStrategy;
}
void throwWeapon(){
this->pWeapon->UseWeapon();
}
};
void test01(){
//创建角色
Character* character=new Character;
//武器策略
WeaponStrategy* knife=new Knife;
WeaponStrategy* ak47=new AK47;
character->setWeapon(knife);
character->throwWeapon();
delete knife;
character->setWeapon(ak47);
character->throwWeapon();
delete ak47;
}
int main(){
test01();
}