23种设计模式一:单例模式

单例模式

先看个例子:

场景目标:点击按钮打开指定的窗口2。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 fm2 = new Form2();
        fm2.Show();

    }
}

但是这样实现有一个问题,每次点击按钮都会打开一个新的窗口2。会产生很多个窗口2,与我们预期只想要打开指定的窗口2,目标不符。

这个时候就需要单例模式:只有一个实例。

怎么做?

第一步:构造函数私有化。

构造函数就是为了初始化对象。相当于Python中__init__函数。此处我们每次点击按钮都会触发new Form2()这个构造函数来新建一个窗口。所以首先想到的是将构造函数私有化。

按【F12】转到Form2这个类,将public修改为private。

public partial class Form2 : Form
{
    //public Form2()
    private Form2()
    {
        InitializeComponent();
    }
}

第二步:提供一个静态方法,返回我们需要的对象。

但是此时有一个新的问题产生,转为私有方法之后,form1里面就无法访问到了,这样一个都创建不了了。所以为了让form1访问到,新创建一个静态方法,将form2对象返回。

为什么是静态?

因为构造函数私有了,就无法外部实例化,只能通过类名静态访问来直接调用这个新方法。所以方法是静态的,返回的是form2对象。静态方法只能调用静态属性。

静态成员只在程序编译时就分配空间了。

无论多少个实例对象,都只有一份静态数据的拷贝。静态成员变量属于类所有,所有对象共享。

***********************为什么不能动态?************************************这点对理解动态静态至关重要********************

静态方法是在类中使用staitc修饰的方法,在类定义的时候已经被装载和分配

而非静态方法是不加static关键字的方法,在类定义时没有占用内存只有在类被实例化成对象时,对象调用该方法才被分配内存。

所以说不实例化,动态方法,外部没法直接用到。类内可以自己调用转手给静态方法调用出去。

所以这个方法:必须是public的,否则外部还是没法访问,然后是static的,不实例化也能访问。类型是Form2的。方法。

public partial class Form2 : Form
{
    //public Form2()
    private Form2()
    {
        InitializeComponent();
    }

    //改变从这里开始
    public static Form2 GetSingle()
    {
        Form2 fm2 = new Form2();
        return fm2;
    }
}

此时在form1代码中点击按钮之后,调用新方法来实现操作:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Form2 fm2 = new Form2();
            // 这里改变了。
            Form2 fm2 = Form2.GetSingle(); // new Form2();
            fm2.Show();
        }
    }

但是操作之后发现,还是没有达到预期效果。

分析原因,因为还是没有根本改变:每次点击按钮新建一个窗口这个本质。

第三步:创建一个单例对象字段

肯定少了关键的一步:唯一性。前面都是铺垫,都在为唯一性铺路。怎么唯一性。类里面有什么唯一?值单一。首先想到字段。

// 全局唯一的单例。字段。
public static Form2 FrmSingle;

这样在新函数方法中,返回这个form2目标类型的字段对象就可以了。

public partial class Form2 : Form
{
    // 全局唯一的单例。字段。
    public static Form2 FrmSingle;

    //public Form2()
    private Form2()
    {
        InitializeComponent();
    }


    public static Form2 GetSingle()
    {
        //这里要改变
        FrmSingle = new Form2();
        return FrmSingle;
    }
}

但是此时还是无法限制个数:

为此需要增加窗体对象个数判断。引入条件判断。检测对象字段状态,有值了就不要赋值了。

修改为:字段初始化为null,如果为null,则建窗口2,否则不操作,返回原来的form2。

public partial class Form2 : Form
{
    // 全局唯一的单例。字段。
    public static Form2 FrmSingle=null;

    //public Form2()
    private Form2()
    {
        InitializeComponent();
    }

    //改变从这里开始
    public static Form2 GetSingle()
    {
        if (FrmSingle==null)
        {
            FrmSingle = new Form2();
        }

        return FrmSingle;
    }
}

总结一:

一、静态方法只能访问静态方法和静态成员。

二、非静态方法要被实例化才能被静态方法调用。

总结二:

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建(类内 创建 目标对象 字段)这个实例的一种模式。

总结三:

应用场景:不需要实例化,特指就是那个。

1、一个班级只有一个班主任。

2、只有一台激光雷达、驱动马达、一个摄像头。

3、一台电脑两台打印机一个文档。

这种场景,最好的做法,直接将字段和方法全写成静态的类名直接调用方法就成了。

单一模块,反复多次调用,写成静态类和方法。因为Console.WriteLine()常用,所以写成静态方法。免得每次用之前还要实例化。


C++中的静态成员实现单例模式

class Printer{
public:
    // 通过静态方法返回静态单例。
	static Printer* getInstance(){ return pPrinter;}
	void PrintText(string text){
		cout << "打印内容:" << text << endl;
		cout << "已打印次数:" << mTimes << endl;
		cout << "--------------" << endl;
		mTimes++;
	}
private:
    // 将 默认构造函数 和 拷贝构造函数 私有化,防止外部创建实例。
	Printer(){ mTimes = 0; }
	Printer(const Printer&){}
private:
	static Printer* pPrinter;
	int mTimes;
};

Printer* Printer::pPrinter = new Printer;  // 静态变量类外初始化

void test(){
	Printer* printer = Printer::getInstance();
	printer->PrintText("离职报告!");
	printer->PrintText("入职合同!");
	printer->PrintText("提交代码!");
}

待总结:

5. 单例模式 — Graphic Design Patterns

http://c.biancheng.net/view/1338.html

单例模式 | 菜鸟教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值