深入原理64式:25 设计模式知识总结

目标:
整理设计模式知识,主要包含如下内容:
1、基础
2、单例模式
3、简单工厂
4、抽象工厂
5、策略模式
6、观察者模式
7、代理模式

第一部分 基础
1 面向对象的设计原则有哪些?
单一职责,开放封闭,依赖倒置,接口隔离,Liskov替换。
单一职责:一个类而言,仅有一个引起它变化的原因。判断如何分离类:多余一个动机改变一个类,这个类还需要分离
开放封闭原则:软件可以扩展,但不可以修改。扩展---开放,更改---封闭。适用:仅对程序中频繁变化的部分进行抽象

依赖倒转原则: 高层模块和底层模块都依赖抽象。
            问题产生的原因:高层业务逻辑相同时,希望使用不同数据库,希望再利用高层模块,但高层模块与低层的访问数据库绑定在一起了。
本质:高层模块->接口/抽象类
                    |
                低层模块
迪米特法则:最少知识原则。如果两个类不必直接通信,那么这两个类就不应当发生直接的相互作用。
        如果其中一个类,需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

2 设计模式分类有哪些?
分为创建型模式,结构性模式,行为型模式
创建型模式: 用于处理对象创建,隐藏具体类的实例创建。主要有:单例,工厂,抽象工厂等
结构性模式: 装饰模式,代理模式等
行为型模式: 策略模式,观察者模式等

第二部分 单例模式
3 单例模式的作用?请编写一个。
1)保证一个类仅有一个实例,并提供全局访问点。
2)C++实现
#include<iostream>
#include<mutex>
#include<memory>
#include<string.h>

using namespace std;

template<typename T>
class Singleton{
private:
    Singleton(){}
    Singleton(const Singleton&){}
    ~Singleton(){}
    Singleton& operator=(const Singleton&){}
public:
    static T* instance()
    {
        if(0 == _instance.get())
        {
            std::unique_lock<std::mutex> uLock(_mutex);
            if(0 == _instance.get())
            {
                std::shared_ptr<T> temp(new T);
                _instance = temp;
            }
        }
        return _instance.get();
    }
private:
    static std::shared_ptr<T> _instance;
    static std::mutex _mutex;
};

template<typename T>
std::shared_ptr<T> Singleton<T>::_instance;

template<typename T>
mutex Singleton<T>::_mutex;

class Service
{
public:
    void run()
    {
        cout<< "Service" << endl;
    }
    Service(){}
    ~Service(){}
};

typedef Singleton<Service> SService;

void process()
{
    SService::instance()->run();
    Service* p1 = SService::instance();
    cout << p1 << endl;
    Service* p2 = SService::instance();
    cout << p2 << endl;
    if(p1 == p2)
    {
        cout << "Singleton OK" << endl;
    }else
    {
        cout << "Singleton Wrong" << endl;
    }
}

int main(int argc, char* argv[])
{
    process();
    getchar();
    return 0;
}

解释:

1 双重检查机制:
  //先判断如果第一次创建,然后加锁,然后在判断是否为空,实例化;如果一进入就加锁,那么效率不好;
  //如果判断完了再进入加锁,那么多个进程仍然会多次实例化,
  if(0 == _instance.get())
  {
   //锁定互斥量,在构造时锁定互斥量,析构时自动解锁,保证互斥量的正确操作
   std::unique_lock<std::mutex> uLock(_mutex);
   if(0 == _instance.get())
2     //防止实例化失败,C++中对指针赋值操作并不能保证原子操作,如果有某个线程1执行到这里,
    //赋值到一半,线程1挂起,线程2开始执行,这是_instance出于任何任何
    std::shared_ptr<T> temp(new T);
    _instance = temp;


第三部分 简单工厂
1 什么是简单工厂?请实现一个
1)在工厂类中做判断,从而创造相应的产品。增加新的产品时,就需要修改工厂类。
实例:一家生成处理器的厂家,一个工厂,能够产生两种型号的处理器核。客户需要什么样的处理器核,显示告诉生产工厂。
简单工厂缺点:增加新的产品类型,需要修改工厂类
2)大致代码如下
//简单工厂模式缺点:增加新类型需要修改工厂类
std::shared_ptr<SingleCore> Factory::instance(enum PRODUCT_TYPE type)
{
    //工厂内部判断
    if(type == COREA)
    {
        std::shared_ptr<SingleCore> ptrA(new SingleCoreA);
        return ptrA;
    }
    else if(type == COREB)
    {
        std::shared_ptr<SingleCore> ptrB(new SingleCoreB);
        return ptrB;
    }
    else
    {
        return NULL;
    }
}


第四部分 抽象工厂
1 什么抽象工厂?请实现一个
1) 提供一个创建一系列相关或相互依赖对象的接口,
而无须指定他们具体的类。
简单工厂模式的最大优点:
工厂类中包含了必要的逻辑判断,根据客户端的选择实例化相关的类。对客户端来说,去除了具体产品的依赖。
缺点:增加功能,方法中需要对工厂类中增加条件判断,对扩展开放,对修改也开放。

抽象工厂缺点:如果要增加一个项目表,需要增加三个类,
IProject,SqlServerProject,AccessProject,
需要修改IFactory,SqlserverFactory,AccessFactory
抽象工厂实例:一个项目中使用多个数据库

2)
工厂类伪代码如下
//工厂A:专门用来生产A型号的处理器
shared_ptr<SingleCore> FactoryA::singleInstance()
{
    shared_ptr<SingleCore> ptrA(new SingleCoreA);
    return ptrA;
}
 
shared_ptr<MultiCore> FactoryA::multiInstance()
{
    shared_ptr<MultiCore> ptrA(new MultiCoreA);
    return ptrA;
}
 
//工厂B:专门用来生产B型号的处理器
shared_ptr<SingleCore> FactoryB::singleInstance()
{
    shared_ptr<SingleCore> ptrA(new SingleCoreB);
    return ptrA;
}
 
shared_ptr<MultiCore> FactoryB::multiInstance()
{
    shared_ptr<MultiCore> ptrA(new MultiCoreB);
    return ptrA;
}

调用类调用如下:
void process()
{
    FactoryA factoryA;
    shared_ptr<SingleCore> ptrSinA = factoryA.singleInstance();
    if(ptrSinA)
    {
        ptrSinA->show();
    }
    shared_ptr<MultiCore> ptrMulA =    factoryA.multiInstance();
    if(ptrMulA)
    {
        ptrMulA->show();
    }
 
    FactoryB factoryB;
    shared_ptr<SingleCore> ptrSinB = factoryB.singleInstance();
    if(ptrSinB)
    {
        ptrSinB->show();
    }
    shared_ptr<MultiCore> ptrMulB =    factoryB.multiInstance();
    if(ptrMulB)
    {
        ptrMulB->show();
    }
}

第五部分 策略模式
1 什么是策略模式?代码?
制定一系列的算法,然后封装起来,使他们可以相互替换。本模式使得算法
可以独立于使用它的客户而变化,算法完成的功能一样。只是各自实现存在差异。
实例:
Cache替换算法,有先进先出,LRU,随机
2

enum RA_TYPE{LRU , FIFO , RANDOM};//标签
template<class RA>
class Cache
{
public:
    /*
    Cache(void);
    ~Cache(void);
    void replace();
    */
    //传入标签,客户只需要知道算法的相应标签即可,不需要知道算法的具体定义。
    Cache(enum RA_TYPE ra)
    {
        if(ra == LRU)
        {
            _ptrRA.reset(new LRU_ReplaceAlgorithm());
        }
        else if(ra == FIFO)
        {
            _ptrRA.reset(new FIFO_ReplaceAlgorithm());
        }
        else if(ra == RANDOM)
        {
            _ptrRA.reset(new Random_ReplaceAlgorithm());
        }
        else
        {
            _ptrRA = NULL;
        }
    }
    Cache(void){}
    ~Cache(void){}
    void replace(){_ra.replace();}
    void replace2(){_ptrRA->replace();}
private:
    RA _ra;
    std::shared_ptr<ReplaceAlgorithm> _ptrRA;
};

第六部分 观察者模式 
1 什么是观察者模式?具体组成是什么?代码
1)定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,
当这个主题对象状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
2)
Subject:通知者
Subject:它所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。
抽象主题提供接口,可以增加和删除观察者对象
Observer:抽象观察者,为所有的具体观察者定义一个接口。在得到主题的通知时更新自己。
ConcreteSubject:具体主题,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知
ConcreteObserver:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
实际上就是双父类的风格,不要依赖具体,使得各自的变化不会影响另一边的变化。
3 伪代码如下:
主题:

class Boss :
    public Subject
{
public:
    Boss(void);
    ~Boss(void);
    void attach(std::shared_ptr<Observer> ptrObserver);
    void detach()
    {
        if(!_vecPtrObservers.empty())
        {
            
        }
    }

    void notify()
    {
        for(unsigned i = 0 ; i < _vecPtrObservers.size() ; i++)
        {
            _vecPtrObservers.at(i)->show();
        }
    }
private:
    std::vector< std::shared_ptr<Observer> > _vecPtrObservers;
    //可能这边强制转换为Observer导致多态失败,这里可能需要存放智能指针
    std::string _sAction;
};

观察者:
//观察者被主题者通知
class Observer
{
public:
    //Observer(const std::string& sName , Subject& subject);
    Observer(const std::string& sName , std::shared_ptr<Subject> ptrSubject);
    virtual ~Observer(void);
    virtual void show();
protected:
    std::string _sName;
    std::shared_ptr<Subject> _ptrSubject;
};

调用者:
void process()
{
    std::shared_ptr<Subject> mPtr(new Boss());
    machaoPtr->_sStatus = "我归来";
    std::shared_ptr<Observer> ptrStockObserver(new StockObserver("陈",mPtr));
    std::shared_ptr<Observer> ptrNbaObserver(new NBAObserver("华",mPtr));
    mPtr->attach(ptrStockObserver);
    mPtr->attach(ptrNbaObserver);
    mPtr->notify();
}

第七部分 代理模式
1 什么是代理模式?代码?
1)为其他对象提供一种代理以控制对这个对象的访问
Subject类:定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方使用Proxy
例子:
安全代理:控制真是对象访问时的权限
关键:代理模式聚合了真正的主类去,在代理中的方法全部源自真正主类的方法

调用者:
void process()
{
    SchoolGirl panyin("潘颖");
    Proxy agent(panyin);
    agent.giveChocolate();
    agent.giveDolls();
    agent.giveFlower();
}


class SchoolGirl
{
public:
    SchoolGirl(const std::string& sName);
    ~SchoolGirl(void);
    std::string getName();
public:
    std::string _sName;
};

代理:
class Proxy :
    public GiveGift
{
public:
    Proxy(SchoolGirl& mm);
    ~Proxy(void);
    void giveFlower();
    void giveChocolate();
    void giveDolls();
private:
    std::shared_ptr<Pursuit> _ptrPursuit;//关键:代理模式聚合了真正的主类去,在代理中的方法全部源自真正主类的方法
};


参考:
王道程序员求职宝典
https://blog.csdn.net/qingyuanluofeng/article/details/39092085
https://blog.csdn.net/qingyuanluofeng/article/details/40567939
https://blog.csdn.net/qingyuanluofeng/article/details/47433729
https://blog.csdn.net/qingyuanluofeng/article/details/47433639
https://blog.csdn.net/qingyuanluofeng/article/details/47611433

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值