编程旅途是漫长遥远的,在不同时刻有不同的感悟,本文会一直更新下去。
单例模式(Singleton Pattern)属于创建型模式,它提供了一种创建对象的最佳方式。
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
含义:
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
职责角度看,实例化与否不应该由使用方判断,而是应该由自己来判断。将实例化判断过程迁移到GetInstance()函数。
Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它。简单地说就是对唯一实例的受控访问。我们可以更改GetInstance() 函数添加条件和参数实现受控访问。
注意:
实现方式:
将默认构造函数设为私有, 防止其他对象使用单例类的 new 运算符。
新建一个静态构建方法作为构造函数。该函数会“偷偷”调用私有构造函数来创建对象,并将其保存在一个静态成员变量中。此后所有对于该函数的调用都将返回这一缓存对象(判断系统是否已经有这个单例,如果有则返回,如果没有则创建)
检查客户端代码,将对单例的构造函数的调用替换为对其静态构建方法的调用。
需要私有静态成员变量保存单例、公有静态构建方法获取单例、类的构造函数私有化保护单例实例。
应用实例:
优点:
缺点:
使用场景:
与其他模式的关系:
原子操作,是并发编程中”最小的且不可并行化“的操作。本案例中使用原子操作配合互斥锁实现了非常高效的单例模式。互斥锁的代价比普通整数的原子读写高很多,所以在性能敏感的地方添加一个initialized标志位,通过原子检测标志位状态降低互斥锁的次数来提高性能。(也可以使用实例来进行判断,在实例未被创建的时候再加锁处理)
在互斥锁之后还要判断实例是否存在,是因为当多线程的时候,当一个线程处理完退出解锁,另一个在排队等候的线程进入后如果没有实例的判断,那么会再生成一遍实例,没有达到单例的目的。
C# 提供了静态初始化的方法,这种方法可以解决多线程环境下不安全的原因。
C# 给类添加sealed关键字防止子类继承产生多个单例、给静态字段添加readonly修改为只读状态,意味着只能在静态初始化期间或在类构造函数中分配变量。
这种静态初始化的方式是在自己被加载时就将自己实例化,所以被形象地称之为饿汉式单例类,原先的单例模式处理方式是要在被第一次引用时才会自己实例化,这叫懒汉式初始化。
饿汉式初始化是类一加载就实例化的对象,所以要提前占用系统资源。然而懒汉式,又会面临多线程访问的安全性问题,需要做双重锁定才能保证安全。
在golang实现静态初始化,实际上只要把实例化的过程移动到当前文件的init函数中,在包被加载的过程中,会首先运行各个文件的init函数,再运行main函数。
在C#经常有工具类之说,这个工具类包含许多静态方法和静态属性。但是这种实用类没有单例类的状态。实用类不能用于继承多台,而单例类虽然实例唯一,但是可以有子类来继承。实用类是一些方法属性的集合,单例是有着唯一对象的实例。

本程序实现了单例模式,三个工作者需要各自找到电梯搭乘!电梯只有一个!
PS C:\Users\小能喵喵喵\Desktop\设计模式\单例模式> go run .
向海宁 正在搭乘电梯!
田海彬 正在搭乘电梯!
package main
import (
"fmt"
"sync"
"sync/atomic"
)
type People string
type Elevator struct {
passengers map[People]bool
}
var (
elevator *Elevator
initialized uint32
mu sync.Mutex
)
// 饿汉式单例
func init() {
initialized = 1
elevator = &Elevator{make(map[People]bool)}
}
// 乘客进电梯
func (p People) intoElevator() {
e := ElevatorGetInstance()
e.passengers[p] = true
}
// 乘客出电梯
func (p People) outElevator() {
e := ElevatorGetInstance()
delete(e.passengers, p)
}
// 乘客按下电梯楼层按钮
func (p People) pressButton() {
e := ElevatorGetInstance()
e.start()
}
// 电梯开始运作
func (e *Elevator) start() {
for k := range e.passengers {
fmt.Println(k, "正在搭乘电梯!")
}
}
// 由于Golang不支持静态方法、静态字段,所以使用纯函数替代面向对象中的静态方法
// 乘客想知道电梯在哪,单例模式
func ElevatorGetInstance() *Elevator {
if atomic.LoadUint32(&initialized) == 1 {
return elevator
}
mu.Lock()
defer mu.Unlock()
// ^ 懒汉式单例
if elevator == nil {
elevator = &Elevator{make(map[People]bool)}
atomic.StoreUint32(&initialized, 1)
}
return elevator
}
package main
// 单例模式
// by 小能喵喵喵 2022年9月8日
func main() {
var workerA, workerB, workerC People = "陈冰", "向海宁", "田海彬"
workerA.intoElevator()
workerB.intoElevator()
workerC.intoElevator()
// workerA 发现自己电梯坐错了
workerA.outElevator()
// workerB 按下了电梯按钮
workerB.pressButton()
}
PS C:\Users\小能喵喵喵\Desktop\设计模式\单例模式> go run .
向海宁 正在搭乘电梯!
田海彬 正在搭乘电梯!
class Singleton
{
private static Singleton instance;
private Singleton() //使用 private 字段外界无法使用new手动创建实例,只能通过静态方法创建
{
}
public static Singleton GetInstance()
{
if(instance == null)
{
instance = new Singleton();
}
return instance
}
}
所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显示定义的构造方法,默认的构造方法就会失效。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json