【软件设计师中级】享元模式学习笔记(c++)

目录

1、Flyweight

(1)意图

(2)结构

(3)适用性

2、根据uml编写代码

(1)泛化关系

(2)关联关系

(3)UML的理解

3、代码实现


1、Flyweight

(1)意图

    运用共享技术有效地支持大量细粒的对象

(2)结构

  

 flyweight描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。

concreteflywegiht实现flyweight接口,并为内部状态增加储存空间,concreteflyweight对向必须可共享的。它所储存的状态必须是内部的,它必须独立于concreteflyweight对象的场景。

并非所有的flyweight子类都需要被共享。flyweight接口使共享成为可能,但并不强制共享。在flyweight对象结构的某些层次,unsharedconcreteflyweight对象通常将concreteflayweight对象作为子节点。

flyweightfactory创建并非管理flyweight对象;确保合理的共享flyweight,当用户请求一个flyweight时,flyweight对象提供一个创建的实例或者在不存在时创建一个实例。

client唯一一个对flyweight的引用;计算或储存一个或多个flyweight的外部状态。

(3)适用性

一个应用程序使用了大量的对象。

完全由于使用大量的对象,造成很大开销。

对象的大多数状态都可以为外部状态。

如果删除兑现的外部状态,那么可以用相对较少共享对象取代多组对象。

应用程序不依赖于对象标识,由于flyweight对象可被共享,所以对于概念上明显有别的对象,表示测试将返回真值。

2、根据uml编写代码

(1)泛化关系

 所谓泛化关系,我们简单里的理解即为为父类与子类的关系,本uml图中flyweight类为unsharedconcreteflyweigh类和concreteflayweight类的父类。

(2)关联关系

flyweightfactory为flyweight特殊关联关系聚合,即在flyweightfactory中有一个“flyweight*”指向flyweight的指针,实现对flyweight的操作。

(3)UML的理解

    首先我们根据教材适用性来理解,一个应用程序使用了大量的对象;由于使用大量的对象,造成很大开销;对象的大多数状态都可以为外部状态。通过这三句话我们可以做如下理解,假如我们要开发一个卖咖啡和茶的饮料店软件,那么我们卖出一个红茶要new一个对象,我们生成一个绿茶又要new一个对象,我们做一个抹茶又要new一个对象。这样我们的茶类的商品越丰富,我们需要new的东西就越来越多。咖啡类商品也一样,奶昔咖啡要new、摩卡要new,假如咖啡种类也很多我们需要new的内容也会越来越多,这就意味着我们使用大量的对象,意味着有大量的开销

 假如我们做如下假设:

奶昔咖啡=咖啡+奶昔部分;

拿铁咖啡=咖啡+拿铁部分;

如果我们这样实现程序的表现的化,奶昔咖啡和拿铁的咖啡部分就可以共用一个new。奶昔部分和拿铁部分我们可以把它理解为外部状态,在实际操作中我们可以用一个链表对外部状态进行储存,若有必要我们可以进行操作或者修改,例如飞行游戏中,飞机射出大量的子弹,我们可以享元模式中,众多子弹可以公用一个new,子弹在界面的位置可以作为外部变量存在链表之中,按时间推移,我们修改子弹的图的位置实现子弹运动的效果。

子弹共用一个new,外部属性为子弹的“位置”

UML图中也有不允许共享的部分,这点非常好理解,还是卖咖啡和茶的饮料店的店的例子,这个饮料点如果它也卖可乐、雪碧等第三方饮料这种饮料就不存共享了。

3、代码实现

    暂未写析构部分

#include<iostream>
#include<list>
using namespace std;
class taset{//用于存储外部状态
    public:
        taset(string mixture){
            this->mixture=mixture;
        }
        string mixture; 
};
class flyweight{//饮料店
    public:
        virtual void operation()=0;
        virtual void operation(const string& ,const string&)=0;
        string taste;
};

class concreteflyweight_tea:public flyweight{//煮茶部分
    public:
        void operation(){
            cout<<"复杂的煮茶过程"<<endl;
            cout<<"====================="<<endl;
        }

        void operation(const string& drinkname,const string& taset){}

};
class concreteflyweight_cofee:public flyweight{//咖啡部分
    public:
        void operation(){
            cout<<"复杂的煮咖啡过程"<<endl;
            cout<<"====================="<<endl;      
        }

        void operation(const string& drinkname,const string& taset){}
};


class unsharedconcreteflyweight_other:public flyweight{//可乐、雪碧、芬达等外部产品,逻辑上无法使用享元模式实现共享
    public:
        void operation(){    
        }
        void operation(const string& drinkname,const string& taset){

            cout<<"店员制作"<<drinkname<<"加"<<taset<<endl;
            cout<<"====================="<<endl;      

        }
};
class flyweightfactory{//享元工厂,用于对flyweight类(饮料店)的操作
    public:
        void getflyweight(string key, string this_taset){
            if(key=="tea"or key=="茶"){

                if(tea==NULL){//享元方式,第一次使用创建,后续就不再创建,直接使用。
                    cout<<"首次使用原味茶叶配方"<<endl;
                    tea=new concreteflyweight_tea();
                }
                else{
                    cout<<"原味茶叶配方已创建"<<endl;
                }
                findtaset(tea,this_taset);//实现外部状态
            }
            else if(key=="cofee"or key=="咖啡"){

                if(cofee==NULL){
                    cout<<"首次使用原味咖啡配方"<<endl;
                    cofee=new concreteflyweight_cofee();
                }
                else{
                    cout<<"原味咖啡配方已创建"<<endl;
                }
                findtaset(cofee,this_taset);
            }else{

                other=new unsharedconcreteflyweight_other();
                other->operation(key,this_taset);
            }


        }
        void findtaset(flyweight *drink,string this_taset){
            typedef list<taset*>::iterator IT;
            for(IT it=mylist.begin();it!=mylist.end();it++){//通过对链表进行遍历,若表中存有就直接使用,没有就创建一个并存在链表中
                if((*it)->mixture==this_taset){
                    cout<<this_taset<<"这个口味已经创建"<<endl;
                    drink->operation();
                    return ;//找到后马上return结束该方法
                }
            }
            cout<<this_taset<<"是一个新的口味我们需要记录一下"<<endl;//在链表中没有找到
            taset *newtaset=new taset(this_taset);//创建一个外部状态
            mylist.push_back(newtaset);//把创建的外部状态存入list中
            drink->operation();
        }

    private:
        list<taset*>mylist;
        flyweight *tea;
        flyweight *cofee;
        flyweight *other;//非共享
};
int main(){
    flyweightfactory* a=new flyweightfactory;
    a->getflyweight(  "tea","抹茶"   );
    a->getflyweight(  "茶","抹茶"   );
    a->getflyweight(  "tea","红茶"   );
    a->getflyweight(  "cofee","奶昔"   );
    a->getflyweight(  "tea","红茶"   );
    a->getflyweight(  "tea","红茶"   );
    a->getflyweight(  "咖啡","奶昔"   );
    a->getflyweight(  "可乐","冰"   );
    return 0;
}

 运行结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值