基本设计模式:单例模式和工厂模式代码实现

单例模式

      单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能阻止你实例化多个对象。一个最好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

      也就是说,很多时候我们需要全局的对象,如一个工程中,数据库访问对象只有一个,这时,可以考虑使用单例模式。单例模式比全局对象好还包括:单例类可以继承,如下例中的C++代码。

     单例模式的关键点在于:构造函数私有,静态的GetInstance

     另外,在C++中必须注意内存的释放。C++、Java、C#中还要注意多线程时的同步问题,另外在多线程可以以合适的方式保证共享变量仅初始化一次

 

以下列出懒汉式的单例模式

C++实现:

复制代码
class Singleton  
{  
  public:  
    static Singleton * GetInstance()  
    {  
        if(NULL == m_pInstance)  
            m_pInstance = new Singleton();  
        return m_pInstance;  
    }  
    static void Release()                    //必须,否则会导致内存泄露   
    {  
        if(NULL != m_pInstance)  
        {  
            delete m_pInstance;  
            m_pInstance = NULL;  
        }  
    }  
      
   protected:  
     Singleton()  
     {  
         cout<<"C++ Singleton"<<endl;  
     };  
     static Singleton * m_pInstance;  
}; 

Singleton* Singleton::m_pInstance = NULL;  
  
class SingleDraw:public Singleton  
{  
public:  
    static SingleDraw* GetInstance()  
    {  
        if(NULL == m_pInstance)  
            m_pInstance = new SingleDraw();  
        return (SingleDraw*)m_pInstance;  
    }  
protected:  
    SingleDraw()  
    {  
        cout<<"C++ SingleDraw"<<endl;  
    }  
};  
  
int main()  
{  
    SingleDraw* s1 = SingleDraw::GetInstance();  
    SingleDraw* s2 = SingleDraw::GetInstance();  
    s2->Release();  
    return 0;  
}  
复制代码

 

Java实现(这里仅给出类实现部分):

复制代码
public class Singleton{

     private static Singleton instance=NULL;
     
     private Singleton(){
          System.out.println("Java Singleton");
     }

     public static Singleton getInstance(){
          if(instance == NULL)
               instance = new Singleton();
          return instance;
     }
}
复制代码


还有另一种形式: 饿汉单例,也就是,类被加载的时候就已经创建好了单例,相比懒汉式只是加载new的地方发生了改变,这里代码重略

 

饿汉式和懒汉式的比较:

1 饿汉式单例,由于类被加载的时候就将自己实例化,所以,从资源利用的角度来说,饿汉式单例比懒汉式单例效率更差

2 懒汉式单例在实例化的时候,必须处理好多个线程同时引用造成的访问限制问题.也就是,很有可能有两个线程同时去调用了这个获取单例的方法,造成了单例被创建了多次懒汉式单例模式线程安全问题:假如现在有两个线程A和线程B,线程A执行到 this.singletonPattern = new SingletonPattern(),正在申请内存分配,可能需要0.001微秒,就在这0.001微秒之内,线程B执行到if(this.singletonPattern == null),你说这个时候这个判断条件是true还是false?是true,那然后呢?线程B也往下走,于是乎就在内存中就有两个SingletonPattern的实例了。所以,在编写懒汉式单例模式时,应注意线程安全问题(由全局变量及静态变量引起的),这里可以用互斥同步的方式去解决。(面试可考的地方)

饿汉式单例类可以在Java 语言内实现, 但不易在C++ 内实现因为静态初始化在C++ 里没有固定的顺序,因而静态的m_instance 变量的初始化与类的加载顺序没有保证,可能会出问题。这就是为什么GoF 在提出单例类的概念时,举的例子是懒汉式的。他们的书影响之大,以致Java 语言中单例类的例子也大多是懒汉式的

 

工厂模式

首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、这里所讲述的工厂方法模式、以及抽象工厂模式。工厂模式是编程中经常用到的一种模式。它的主要优点有:

  • 可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品
  • 对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
  • 降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。

C++实现:

复制代码
#include <iostream>

using namespace std;

class IProduct
{
public:
    virtual void productMethod() = 0;
};


class Product:public IProduct
{
public:
    void productMethod() 
    {  
        cout<<"C++ productMethod call"<<endl;  
    }  
};


class IFactory
{
public:
    virtual IProduct* CreateProduct() = 0;
};


class ConcreateFactory:public IFactory
{
public:
   IProduct* CreateProduct()
   {
        IProduct* p = new Product();
        return p;
   }
};

int main()
{
   IFactory* pFactory = new ConcreateFactory();

   IProduct* p = pFactory->CreateProduct();

   p->productMethod();

   delete p;

   return 1;
}
复制代码


Java实现

复制代码
interface IProduct {  
    public void productMethod();  
}  
  

class Product implements IProduct {  
    public void productMethod() {  
        System.out.println("Java productMethod call");  
    }  
}  
  

interface IFactory {  
    public IProduct createProduct();  
}  
  

class Factory implements IFactory {  
    public IProduct createProduct() {  
        return new Product();  
    }  
}  
  

public class Client {  
    public static void main(String[] args) {  
        IFactory factory = new Factory();  
        IProduct prodect = factory.createProduct();  
        prodect.productMethod();  
    }  
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值