设计模式详解十一:Flyweight模式

flyweight意思是轻量级,该模式主要为了解决有些场景会产生许多对象,并且其中的许多对象都是相同的。flyweight提供创建对象接口,并且内部保存对象池,当请求的对象没有在对象池中,那么重新创建对象放入对象池,如果请求的对象存在对象池中,那么直接从对象池取出对象返回给请求者,从而避免对象的频繁创建,造成系统开销的问题。

一、设计模式的结构图

Flyweight模式,FlyweightFactory根据key值提供获取Flyweight对象的接口,

二、程序代码实现

1、基类Flyweight的定义和实现

/// 类的定义
class Flyweight
{
public:
    virtual ~Flyweight();
    virtual void Operation(const std::string& strParam);
    std::string GetState();
    
protected:
    Flyweight(std::string strState);
private:
    std::string m_strState;
};

/// 类的实现
Flyweight::Flyweight(std::string strState)
{
    this->m_strState = strState;
}

Flyweight::~Flyweight()
{
}

void Flyweight::Operation(const std::string& strParam)
{
}
string Flyweight::GetState()
{
    return this->m_strState;
}

2、子类SubFlyweight的定义和实现

/// 类的定义
class SubFlyweight:public Flyweight
{
public:
    SubFlyweight(std::string strState);
    ~SubFlyweight();
    
    void Operation(const std::string& strParam);

protected:
private:
};


/// 类的实现
SubFlyweight::SubFlyweight(std::string strState):Flyweight(strState)
{
    DEBUG_LOG("SubFlyweight Build..... ", strState);
}

SubFlyweight::~SubFlyweight()
{
}

void SubFlyweight::Operation(const string& strParam)
{

}

3、FlyweightFactory工厂类的定义和实现

/// 类的定义
class FlyweightFactory
{
public:
    FlyweightFactory();
    ~FlyweightFactory();
    Flyweight* GetFlyweight(const std::string& key);
    
protected:
private:
    vector<Flyweight*> m_fly;
};


/// 类的实现
FlyweightFactory::FlyweightFactory()
{
}

FlyweightFactory::~FlyweightFactory()
{
}

Flyweight* FlyweightFactory::GetFlyweight(const std::string& key)
{
    vector<Flyweight*>::iterator it = m_fly.begin();
    for (; it != m_fly.end();it++)
    {
        if ((*it)->GetState() == key)
        {
            cout<<"already created by users...."<<endl;
            return *it;
        }
    }
    Flyweight* fw = new SubFlyweight(key);
    m_fly.push_back(fw);
    return fw;
}

三、测试验证结果

1、主程序输入如下所示的测试代码

FlyweightFactory* fc = new FlyweightFactory();
Flyweight* fw1 = fc->GetFlyweight("li");
Flyweight* fw2 = fc->GetFlyweight("zheng!");
Flyweight* fw3 = fc->GetFlyweight("li");

2、运行结果如下所示,第三次请求对象,因为已经存在在对象池中,所以直接从对象池中获取对象并返回

[2019-09-14 19:54:45.160  SubFlyweight:31]  SubFlyweight Build.....  = li
[2019-09-14 19:54:45.160  SubFlyweight:31]  SubFlyweight Build.....  = zheng!
already created by users....

四、总结

FlyweightFactory类采用vector存储对象,当然需要根据具体场景来选择合适的容器,比如,map、hash表等。需要注意的是FlyweightFactory查找的key值是存放在Flyweight对象中的成员变量。

设计模式详解十:外观模式

外观模式,即Facade模式,封装了内部细节,对外提供统一接口。比如做一件事的时候,需要经过几个步骤,但是使用者并不关心内部细节,因此,这时候就可以采用外观模式,将几个步骤封装起来,然后提供一个统一的接口。

一、设计模式的结构图

外观模式对外提供统一接口OperationWrapper, 内部封装两个子系统的接口。

二、程序代码实现

1、定义和实现子系统类1

/// 类的定义
class Subsystem1
{
public:
    Subsystem1();
    ~Subsystem1();
    void Operation();
    
protected:
private:
};


/// 类的实现
Subsystem1::Subsystem1()
{
}

Subsystem1::~Subsystem1()
{
}

void Subsystem1::Operation()
{
    DEBUG_LOG("", "Subsystem1 operation...");
}

2、定义和实现子系统类2

/// 类的定义
class Subsystem2
{
public:
    Subsystem2();
    ~Subsystem2();
    void Operation();

protected:
private:
};


/// 类的实现
Subsystem2::Subsystem2()
{
}

Subsystem2::~Subsystem2()
{
}
void Subsystem2::Operation()
{
    DEBUG_LOG("", "Subsystem2 operation...");
}

3、定义和实现外观模式

/// 类的定义
class Facade
{
public: Facade();
    ~Facade();
    void OperationWrapper();

protected:
private:
    Subsystem1* m_subs1;
    Subsystem2* m_subs2;
};


/// 类的实现
Facade::Facade()
{
    this->m_subs1 = new Subsystem1();
    this->m_subs2 = new Subsystem2();
}

Facade::~Facade()
{
    delete m_subs1;
    delete m_subs2;
}

void Facade::OperationWrapper()
{
    this->m_subs1->Operation();
    this->m_subs2->Operation();
}

从外观模式类看,它负责控制两个子系统类的创建和销毁,对外提供统一接口,内部实现调用两个子系统的函数。

三、测试验证结果

1、主程序输入如下所示的测试代码

Facade* facade = new Facade();
facade->OperationWrapper();

2、运行结果如下所示

[2019-09-08 16:16:18.993  Operation:21]   = Subsystem1 operation...
[2019-09-08 16:16:18.993  Operation:34]   = Subsystem2 operation...

四、总结

外观模式在实际中应用比较广泛,它通常采用单例模式实现,比如采用外观模式封装各个对象的创建过程。

设计模式详解九:迭代器模式

迭代器模式, 即iterator模式,封装集合对象,提供访问集合的接口。

一、设计模式的结构图

迭代器模式的处理逻辑是:iterator迭代器内部保存持有集合对象,用于访问集合,而集合提供创建返回迭代器的函数接口。

二、程序代码实现

1、 定义实现迭代器的基类

#ifndef Object
typedef int Object;
#endif


/// 类定义
class Iterator
{
public:
    virtual ~Iterator();
    virtual void First() = 0;
    virtual void Next() = 0;
    virtual bool IsDone() = 0;
    virtual Object CurrentItem() = 0;
    
protected:
    Iterator();
private:
};


/// 类实现

Iterator::Iterator()
{
    
}

Iterator::~Iterator()
{
    
}

2、 定义实现迭代器的子类

/// 类的定义
class Aggregate;
class ConcreteIterator : public Iterator
{
public:
    ConcreteIterator();
    ConcreteIterator(Aggregate *ag, int idx = 0);
    ~ConcreteIterator();
    void First();
    void Next();
    bool IsDone();
    Object CurrentItem();

protected:
private:
    Aggregate* m_ag;
    int m_idx;
};

/// 类的实现
ConcreteIterator::ConcreteIterator()
{
    
}

ConcreteIterator::ConcreteIterator(Aggregate *ag, int idx)
{
    this->m_ag = ag;
    this->m_idx = idx;
}

ConcreteIterator::~ConcreteIterator()
{
}

Object ConcreteIterator::CurrentItem()
{
    return m_ag->GetItem(m_idx);
}

void ConcreteIterator::First()
{
    m_idx = 0;
}

void ConcreteIterator::Next()
{
    if (m_idx < m_ag->GetSize())
    {
        m_idx++;
    }
}

bool ConcreteIterator::IsDone()
{
    return (m_idx == m_ag->GetSize());
}

3、定义实现集合的基类

#ifndef Object
typedef int Object;
#endif

/// 类的定义
class Iterator;
class Aggregate
{
public:
    virtual ~Aggregate();
    virtual Iterator* CreateIterator() = 0;
    virtual Object GetItem(int idx) = 0;
    virtual int GetSize() = 0;
    
protected:
    Aggregate();
private:
};


/// 类的实现
Aggregate::Aggregate()
{
}

Aggregate::~Aggregate()
{
}

4、定义实现集合的子类

/// 类的定义
class ConcreteAggregate:public Aggregate
{
public:
    enum {SIZE = 3};
    ConcreteAggregate();
    ~ConcreteAggregate();
    Iterator* CreateIterator();
    Object GetItem(int idx);
    int GetSize();
    
protected: private:
    Object m_objs[SIZE];
};


/// 类的实现
ConcreteAggregate::ConcreteAggregate()
{
    for (int i = 0; i < SIZE; i++)
        m_objs[i] = i;
}

ConcreteAggregate::~ConcreteAggregate()
{
}

Iterator* ConcreteAggregate::CreateIterator()
{
    return new ConcreteIterator(this);
}

Object ConcreteAggregate::GetItem(int idx)
{
    if (idx < this->GetSize())
    {
        return m_objs[idx];
    }
    else
    {
        return -1;
    }
}

int ConcreteAggregate::GetSize()
{
    return SIZE;
}

 

三、测试验证结果

1、主程序输入如下所示的测试代码

Aggregate* ag = new ConcreteAggregate();
Iterator* it = new ConcreteIterator(ag);
for (; !(it->IsDone()) ; it->Next())
{
    std::cout<< "item = "<< it->CurrentItem()<<std::endl;
}

2、运行结果如下所示,迭代器访问集合内的所有数据,并输出显示

item = 0
item = 1
item = 2

四、总结

迭代器的实现过程中,为了避免集合过多的暴露公有接口,可以将迭代器声明为集合的友元,来访问集合的私有数据。另外,从上面的代码实现中,可以看出集合提供创建迭代器的接口,而迭代器持有集合对象,内部包装集合的访问接口。