温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

设计模式(创建型)之单例模式

发布时间:2020-08-05 13:48:29 来源:网络 阅读:325 作者:yanchao520mmmm 栏目:软件技术

单例模式的目的就是要控制特定的类只产生一个对象,当然也允许在一定情况下灵活的改变对象的个数。

 

怎么来实现单例模式呢?

一个类的对象的产生是由类构造函数来完成的,如果想限制对象的产生,一个办法就是:

1,将构造函数变为私有的(至少是受保护的),使得外面的类不能通过引用来产生对象;

2,同时为了保证类的可用性,就必须提供一个自己的对象以及访问这个对象的静态方法

 

单例模式可分为有状态的和无状态的。

有状态的单例对象一般也是可变的单例对象,多个单态对象在一起就可以作为一个状态仓库一样向外提供服务。

没有状态的单例对象也就是不变单例对象,仅用做提供工具函数。

 

UML类图:

设计模式(创建型)之单例模式

实现:

java:

一、饿汉式:

singleton1.java:

/*
 * 创建人:颜超
 * 创建时间:2013-6-26
 * 文件名:singleton1.java
 * 创建型设计模式
 * 单例(singleton)
 * 饿汉式
 */
public class Singleton1 {
 //在自己内部定义自己一个实例
 //注意这是private 只供内部调用
 private static Singleton1 instance = new Singleton1();
 //将构造函数设置为私有
 private Singleton1(){
  System.out.println("new an instance!");
 }
 //静态工厂方法,提供了一个供外部访问得到对象的静态方法
 public static Singleton1 getInstance(){
  return instance;
 }
 public static void main(String[] args) {
  Singleton1.getInstance();
 }
}

二、懒汉式:

singleton2.java:

/*
 * 创建人:颜超
 * 创建时间:2013-6-26
 * 文件名:singleton2.java
 * 创建型设计模式
 * 单例(singleton)
 * 懒汉式
 */
public class Singleton2 {
 private static Singleton2 instance = null;
 private Singleton2(){
  System.out.println("new an instance!");
 }
 //对静态工厂方法进行了同步处理,原因很明显——为了防止多线程环境中产生多个实例
 //将类对自己的实例化延迟到第一次被引用的时候。而在"饿汉式"则是在类被加载的时候实例化,这样多次加载会造成多次实例化
 public static synchronized Singleton2 getInstance(){
  if (instance == null){
   instance = new Singleton2();
  }
  return instance;
 }
 public static void main(String[] args) {
 // Singleton1 s1 = new Singleton1();
  Singleton2.getInstance();
 }
}
三、

以上两种实现方式均失去了多态性,不允许被继承。还有另外一种灵活点的实现,将构造函数设置为受保护的,这样允许被继承产生子类。

singleton3.java:

import java.util.HashMap;

public class Singleton3 {
 private static HashMap sinRegistry = new HashMap();
 private static Singleton3 instance = new Singleton3();
 protected Singleton3(){
  System.out.println("Construction for Singleton3!");
 }
 public static Singleton3 getInstance(String name){
  if (name == null){
   name = "Singleton3";
  }
  if (sinRegistry.get(name) == null){
   try{
    sinRegistry.put(name, Class.forName(name).newInstance());
   }catch(Exception e){
    e.printStackTrace();
   }
  }
  return (Singleton3)(sinRegistry.get(name));
 }

 public void test(){
  System.out.println("get Class Success!");
 }
}

class Singleton3Child1 extends Singleton3 {

 public Singleton3Child1(){
  System.out.println("Construction for Singleton3Child1!");
 }
 public static Singleton3Child1 getInstance(){
  return (Singleton3Child1)Singleton3.getInstance("Singleton3Child1");
 }
 public void test(){
  System.out.println("get Child1 Class Success!");
 }
}

class Singleton3Child2 extends Singleton3 {

 public Singleton3Child2(){
  System.out.println("Construction for Singleton3Child2!");
 }
 public static Singleton3Child2 getInstance(){
  return (Singleton3Child2)Singleton3.getInstance("Singleton3Child2");
 }
 public void test(){
  System.out.println("get Child2 Class Success!");
 }
}

testMain.java:

public class testMain {

 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("#########################");
  Singleton3Child1 s3c1 = new Singleton3Child1();
  Singleton3Child2 s3c2 = new Singleton3Child2();
  // 因为hashmap的key值是唯一的,所以,下面的三部分一次只能显示一部分

  System.out.println("#########################");
  Singleton3Child1.getInstance(); //add Singleton3Child1 into hashmap 
  Singleton3Child2.getInstance(); //add Singleton3Child2 into hashmap 
  System.out.println("#########################");
  Singleton3.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap 
  Singleton3.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap 
  System.out.println("#########################");
  Singleton3Child1.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap 
  Singleton3Child1.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap 
  Singleton3Child2.getInstance("Singleton3Child1"); //add Singleton3Child1 into hashmap 
  Singleton3Child2.getInstance("Singleton3Child2"); //add Singleton3Child2 into hashmap 

 }

}

 

由于在 java 中子类的构造函数的范围不能比父类的小,所以可能存在不守规则的客户
程序使用其构造函数来产生实例,造成单例模式失效。

 

C++:

Singleton.cpp:

#include <iostream>
using namespace std;

class Singleton{

public:
 static Singleton* getInstance(){
  if(instance == NULL){
   cout << "There is no instance!!!" << endl;
   instance = new Singleton();
  }
  return instance;
 }
private:
 Singleton(){
  cout << "new an instance!!!" << endl;
 }
 static Singleton* instance;
};

// static variable "instance" can not initialized in class
Singleton* Singleton::instance = NULL;

int main() {
 Singleton::getInstance();
 return 0;
}

 

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI