1.单例模式
单例模式的概念:单例模式是一种对象创建型模型,使用单例模式,可以保证为一个类生成唯一的实例对象,也就是说,在整个程序空间中,该类只存在一个是对象。
为什么要使用单例模式
在系统开发中我们常常有以下需求:
- 在多个线程之间,比如初始化一次socket资源,比如servlet环境,共享同一个资源或者操作同一个对象
- 在整个程序空间使用全局变量,共享资源
- 大规模系统中为了性能的考虑,需要节省对象的创建实践等等
因为单例模式可以保证为一个类只生成唯一的实例对象,这些情况下,单例模式就派上用场了。
单例模式的实现步骤
- 构造函数私有化
- 提供一个全局的静态方法(全局访问点)
- 在类中定义一个静态指针,指向本类的变量的静态变量指针
饿汉式单例和懒汉式单例
懒汉单例:只有在获取单例的时候才创建对象,实现如下::
- #include<stdio.h>
- #include<iostream>
- using namespace std;
- class singelton
- {
- public:
- static singelton *getinstance()
- {
- if(m_singer==NULL)//懒汉模式 每次获取实例都要判断 会有多线程问题
- {
- m_singer=new singelton ;
- }
- return m_singer;
- }
- static void printfT()
- {
- cout<<"m_count:"<<m_count<<endl;
- }
- private:
- static singelton * m_singer;//静态成员在类外初始化
- static int m_count;//静态成员在类外初始化
- singelton()
- {
- m_singer=NULL;
- m_count =0;
- cout<<"执行构造函数"<<endl;
- }
- };
- singelton *singelton ::m_singer =NULL;//懒汉式并没有创建单例对象
- int singelton ::m_count =0;
- int main()
- {
- cout<<"演示 懒汉式"<<endl;
- singelton *p1=singelton ::getinstance ();
- //在使用时才去创建对象
- singelton *p2=singelton ::getinstance ();
- if(p1!=p2)
- {
- cout<<"不是同一个对象"<<endl;
- }
- else
- {
- cout<<"是同一个对象"<<endl;
- }
- p1->printfT ();
- p2->printfT ();
- return 0;
- }
可见构造函数只执行了一次,对象只创建一次
修改上面的代码改为饿汉式
懒汉遇上多线程
饿汉模式,程序一开始就new出来一个对象,不管来多少线程,都不会出错,只能实例化一个对象,但是在懒汉模式下,如果有多个线程想要实例化对象,在不采取任何措施的情况下,可能会产生多个线程。
解决方法:加锁
lock()
unlock()
又出现了一个新的问题,如果有很多线程的话,每次都要加锁会造成系统开销大,所以我们又有一个新的解决办法
那就是双检锁:
我们试想一下如果有一个线程进入到第一个if,加锁,进入到第二个if并创建对象,此时对象已经不再为空,往后所有的线程,在第一个if判断不为空后就不会再加锁。。这样大大减少了加锁的次数。
2 简单工厂模式
通过一个类来创建其他的类的实例
工厂角色
简单工厂模式的黑犀牛,他负责实现创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象
抽象角色
简单工厂模式所创键的所有对象的父类,他负责描述所有实例的公共接口
具体产品角色
简单共产模式所创建的具体实例对象
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例。
这个工厂面向抽象类型编程
简单工厂模式的优缺点:
在这个模式中,工厂类是整个模式的关键所在,他包含必要的逻辑判断,能够根据外界给定的信息,决定究竟应该创建哪个具体的类对象,用户在使用时可以直接根据工厂类创造所需的实例,而无需了解这些对象时如何创建以及组织的,有利于整个软件体系结构的优化,他的缺点也正是在工厂类上面,由于工厂中集中了所有类的创建逻辑,所以高内聚方面做的并不好,另外,当系统中具体产品不断在增多时,可能会出现工厂类也要做相应的修改,扩展性并不好。当想要生产新的产品是,就要修改工厂类。
简单实现
#include<iostream>
using namespace std;
class Fruit//抽象的基类,水果类
{
public :
virtual void getfruit()=0;
};
class Banana:public Fruit //具体产品
{
public:
virtual void getfruit ()
{
cout<<"香蕉"<<endl;
}
protected:
private:
};
class Apple:public Fruit //具体产品
{
public:
virtual void getfruit ()
{
cout<<"苹果"<<endl;
}
protected:
private:
};
class Factory
{
public :
Fruit *create(char *p)
{
if(strcmp(p,"banana")==0)
{
return new Banana;//子类对象,,返回值为父类指针
}
else if(strcmp(p,"Apple")==0)
{
return new Apple;
}
else
{
cout<<"不支持"<<endl;
return NULL;
}
}
private:
protected:
};
int main()
{
Factory *f=new Factory;//创建工厂
Fruit *fruit=NULL;//创建父类指针
//想吃香蕉
fruit=f->create ("banana");
fruit->getfruit ();//父类指针指向子类对象//多态,对调用子类的getfruit()函数
fruit=f->create ("Apple");
fruit->getfruit ();
delete fruit;
delete f;
return 0;
}
!
3 工厂方法模式
概念:工厂方法模式同样属于类的创建型模式,又称为多态工厂模式,意义是,定义一个创建产品对象的工厂接口,将实际创建工作拖迟到子类当中,核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象的好处就是使得工厂方法模式可以使系统在不修改任何具体工厂角色的情况下引进新的产品,
上面的简单工厂模式的缺点是当新增产品的时候就要去修改工厂的类,这就违反了开放封闭原则,(类、模块、函数)可以扩展,但是不可以修改,于是,就出现了工厂方法模式。所谓工厂方法模式,是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。
通俗一点讲:如果我想吃香蕉就创建一个香蕉工厂,让这个香蕉工厂去生产香蕉,,想吃什莫就创建一个什莫样 的共厂
简单实现
- #include<iostream>
- using namespace std;
- class Fruit//抽象的基类,水果类
- {
- public :
- virtual void getfruit()=0;
- };
- class Banana:public Fruit //具体产品
- {
- public:
- virtual void getfruit ()
- {
- cout<<"香蕉"<<endl;
- }
- protected:
- private:
- };
- class Apple:public Fruit //具体产品
- {
- public:
- virtual void getfruit ()
- {
- cout<<"苹果"<<endl;
- }
- protected:
- private:
- };
- class AbFactory //抽象的工厂
- {
- public :
- virtual Fruit * Createproduce()=0;
- private:
- protected:
- };
- class bananafactory :public AbFactory
- {
- virtual Fruit *Createproduce ()
- {
- return new Banana;
- }
- };
- //想吃什莫就new一个什莫样子的工厂
- class AppleFactory :public AbFactory
- {
- virtual Fruit *Createproduce ()
- {
- return new Apple;
- }
- };
- /
- //添加新产品
- ///
- class pear:public Fruit
- {
- virtual void getfruit ()
- {
- cout <<"梨子"<<endl;
- }
- };
- class peraFactory:public AbFactory
- {
- virtual Fruit *Createproduce ()
- {
- return new pear;
- }
- };
- int main()
- {
- AbFactory *vf=NULL;//
- Fruit *fruit=NULL;//创建父类指针
- //想吃香蕉
- vf=new bananafactory ;
- fruit=vf->Createproduce ();
- fruit ->getfruit ();
- delete fruit;
- delete vf;
- //想吃苹果
- vf=new AppleFactory ;//new 一个苹果工厂
- fruit=vf->Createproduce ();//让这个工厂生产苹果,
- fruit ->getfruit ();
- delete fruit;
- delete vf;
- vf=new peraFactory ;//new 一个苹果工厂
- fruit=vf->Createproduce ();//让这个共产生产苹果,
- fruit ->getfruit ();
- delete fruit;
- delete vf;
- return 0;
- }
4 抽象工厂模式
前面所讲的工厂方法模式,只能生产单一的产品,要么生产香蕉,要莫生产西红柿,要模生产苹果,但不能同时生产一个产品组,,也就是说(我想吃南方的香蕉,北方的橘子),这样就没有办法去做到。
现在我们要学的这个抽象工厂就可以生产一个产品族,这就是抽象工厂产生的原因
具体工厂在开闭原则下 ,能生产 香蕉/ 苹果/ 西红柿
抽象工厂在开闭原则下能生产 (西红柿 /香蕉 / 苹果)
(土豆辣椒茄子)//产品族
抽象工厂模式的结构
抽象工厂角色
抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口
具体工厂的角色
具体工厂是抽象工厂的一个实现,负责实例化某个产品族中的产品对象
抽象角色
抽象模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口
具体产品角色
抽象模式所创建的具体实例对象
使用抽象工厂模式一般要满足以下条件
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
- 系统一次只可能消费其中某一族产品,即同族的产品一起使用。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当增加一个新的产品族时不需要修改原代码,满足开闭原则。
- 其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
抽象工厂模式的扩展有一定的“开闭原则”倾斜性
- 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
- 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。
代码分析
#include<iostream>
using namespace std;
class abstractapple
{
public:
virtual void showname()=0;
};
class chinaapple:public abstractapple
{
public :
virtual void showname ()
{
cout<<"中国的苹果"<<endl;
}
};
class usaapple:public abstractapple
{
public :
virtual void showname ()
{
cout<<"美国苹果"<<endl;
}
};
class jaapple:public abstractapple
{
public :
virtual void showname ()
{
cout<<"日本苹果"<<endl;
}
};
class abstractbanana
{
public:
virtual void showname()=0;
};
class chinabababa :public abstractbanana
{
public:
virtual void showname ()
{
cout<<"中国的香蕉"<<endl;
}
};
class usabababa :public abstractbanana
{
public:
virtual void showname ()
{
cout<<"美国的香蕉"<<endl;
}
};
class japbababa :public abstractbanana
{
public:
virtual void showname ()
{
cout<<"日本的香蕉"<<endl;
}
};
class abstractpear
{
public:
virtual void showname()=0;
};
class chinapear:public abstractpear
{
public:
virtual void showname ()
{
cout<<"中国的梨子"<<endl;
}
};
class usapear:public abstractpear
{
public:
virtual void showname ()
{
cout<<"美国的的梨子"<<endl;
}
};
class jappear:public abstractpear
{
public:
virtual void showname ()
{
cout<<"日本的梨子"<<endl;
}
};
class abstractfactory
{
public :
virtual abstractapple *getapple()=0;
virtual abstractbanana *getbanana()=0;
virtual abstractpear *getpear()=0;
};
class chinafactory :public abstractfactory
{
public:
virtual abstractapple *getapple()
{
return new chinaapple;
}
virtual abstractbanana *getbanana()
{
return new chinabababa ;
}
virtual abstractpear *getpear()
{
return new chinapear ;
}
};
class usafactory :public abstractfactory
{
public:
virtual abstractapple *getapple()
{
return new usaapple ;
}
virtual abstractbanana *getbanana()
{
return new usabababa ;
}
virtual abstractpear *getpear()
{
return new usapear ;
}
};
class japfactory :public abstractfactory
{
public:
virtual abstractapple *getapple()
{
return new jaapple ;
}
virtual abstractbanana *getbanana()
{
return new japbababa ;
}
virtual abstractpear *getpear()
{
return new jappear ;
}
};
int main()
{
abstractfactory *abf=NULL;
abstractapple *abapp=NULL;
abstractbanana *abban=NULL;
abstractpear *abpear=NULL;
//中国工厂
abf =new chinafactory ;
abapp =abf -> getapple ();
abban=abf->getbanana ();
abpear =abf->getpear ();
abapp ->showname ();
abban ->showname ();
abpear ->showname ();
delete abpear ;
delete abban ;
delete abapp ;
delete abf;
return 0;
}