Sharing a class instance between two classes
我有两个不同的类,它们都表示需要持久化到数据库中的对象,现在我想在两个类之间共享数据库客户机对象。我希望避免多次实例化客户机对象。
目前,我通过使用全局变量来实现这一点
1 2 3 4 5 6 7 8 9 10 11 12 13 | $client = Mysql2::Client.new(:database =>"myDb", :user =>"user", :password =>"password", :host =>"localhost") class Person def save $client.query("INSERT INTO persons") end end class Car def save $client.query("INSERT INTO cars") end end |
这是可行的,但我想知道是否有更正确的方法来做到这一点,以及为什么它们更正确?
你可以从父类继承。这个功能允许你分享的对象是在普通和干(不要重复自己)规划原则。所以,你想让它保护你的数据库连接和锁定,resuces,游泳池,和任何其他线索,你可能想要做一个没有你担心你的儿童班
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Record @table_name = nil @@client = Mysql2::Client.new(:database =>"myDb", :user =>"user", :password =>"password", :host =>"localhost") def save @@client.query("INSERT INTO #{@table_name}") if @table_name end end class Person < Record @table_name ="persons" end class Car < Record @table_name ="cars" end |
而我们的主题,你应该看看你的数据库使用ActiveRecord模型的处理和连接。它已经是相当多的东西,你会需要将更多的兼容其他宝石已经出去了。它也可以用于讽刺。
在使用作为替代继承,为什么不考虑一个简单的单件模式?这可以让你的模特在清洁,分捡的责任你的班。和消除需要继承。
下面的例子illustrates本。只有一个单实例类的datamanager CAN存在。所以,你只有一次,但它instantiate CAN使用它无处不在。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | require 'singleton' class DataManager include Singleton attr_accessor :last_run_query def initialize() if @client.nil? p"Initialize the Mysql client here - note that this'll only be called once..." end end def query(args) # do your magic here @last_run_query = args end end |
下一步,调用它使用访问器是一个
1 2 3 4 5 6 7 8 9 10 11 | # Fetch, or create a new singleton instance first = DataManager.instance first.query('drop table mother') p first.last_run_query # Again, fetch or create a new instance # this'll actually just fetch the first instance from above second = DataManager.instance p second.last_run_query # last line prints:"drop table mother" |
Singleton模式的记录,有一些downsides CAN和使用它的结果在A没有结尾的辩论对你是否应该使用它。但在我看来它是非常另类的特异性问题。