重构辛格尔顿过度 [英] Refactoring Singleton Overuse

查看:120
本文介绍了重构辛格尔顿过度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我有一种顿悟,这是我做的一切都错了。一些历史:我继承了C#应用程序,这是真正的静态方法只是一个集合的C#code完全程序混乱。我重构这个最好的,我知道的时候,带来了大量的大学毕业后的面向对象的知识。为了使长话短说,许多在code中的实体已被证明是单身。

Today I had an epiphany, and it was that I was doing everything wrong. Some history: I inherited a C# application, which was really just a collection of static methods, a completely procedural mess of C# code. I refactored this the best I knew at the time, bringing in lots of post-college OOP knowledge. To make a long story short, many of the entities in code have turned out to be Singletons.

今天,我意识到我需要3个新的类别,这将每个遵循相同的Singleton模式到软件的其余部分相匹配。如果我继续翻滚而下此滑坡,最终每个班级在我的应用程序将是单身,这将真正没有逻辑上的静态方法原始组不同的。

Today I realized I needed 3 new classes, which would each follow the same Singleton pattern to match the rest of the software. If I keep tumbling down this slippery slope, eventually every class in my application will be Singleton, which will really be no logically different from the original group of static methods.

我需要重新考虑这方面的帮助。我知道依赖注入,而且一般会被打破辛格尔顿诅咒使用策略。但是,我这样做与此相关的重构了几个具体的问题,所有的最佳做法。

I need help on rethinking this. I know about Dependency Injection, and that would generally be the strategy to use in breaking the Singleton curse. However, I have a few specific questions related to this refactoring, and all about best practices for doing so.

  1. 如何接受的是利用静态变量封装配置信息?我在使用静态脑块,我认为这是由于早期的面向对象的类大专以上,其中教授说静不好。但是,我应该有我每次访问时重新配置类?当访问硬件,它是确定离开一个静态的指针所需要的地址和变量,或者我应该继续执行打开()关闭() 操作?

现在我有一个方法充当控制器。具体来说,我不断地轮询多个外部设备(通过硬件驱动程序)的数据。如果这种类型的控制器是要走的路,或者我应该产卵单独的线程每台仪器在程序的启动?如果是后者,我怎么使这个面向对象?我应该创建类名为 InstrumentAListener InstrumentBListener ?还是有接近这方面的一些标准的方式?

Right now I have a single method acting as the controller. Specifically, I continually poll several external instruments (via hardware drivers) for data. Should this type of controller be the way to go, or should I spawn separate threads for each instrument at the program's startup? If the latter, how do I make this object oriented? Should I create classes called InstrumentAListener and InstrumentBListener? Or is there some standard way to approach this?

有没有更好的方式来做到全球配置?现在我只是有 Configuration.Instance.Foo 宽松洒在整个code。几乎每个类使用它,所以也许保持它作为一个Singleton是有道理的。有什么想法?

Is there a better way to do global configuration? Right now I simply have Configuration.Instance.Foo sprinkled liberally throughout the code. Almost every class uses it, so perhaps keeping it as a Singleton makes sense. Any thoughts?

我的许多类都是像 SerialPortWriter DataFileWriter ,必须坐等这个数据流中,由于他们是活跃在整个时间,我应该如何以监听生成的事件安排这些数据的时候进来?

A lot of my classes are things like SerialPortWriter or DataFileWriter, which must sit around waiting for this data to stream in. Since they are active the entire time, how should I arrange these in order to listen for the events generated when data comes in?

任何其他资源,书籍,或如何摆脱单身人士和其他方式过度使用意见将是有益的。

Any other resources, books, or comments about how to get away from Singletons and other pattern overuse would be helpful.

推荐答案

好吧,这是我最好的拍摄,在攻击这个问题:

Alright, here's my best shot at attacking this question:

(1)静

静态的问题,你可能有是,它意味着不同的东西在.NET中说,C ++。静态基本上意味着它是在类本身访问。至于它的接受 ID说,它更多的东西,你会用来做非实例具体操作上的一类。或者就像 Math.Abs​​一般的东西(...)。你应该使用一个全局配置可能是持有当前/主动配置静态访问属性。另外,也许一些静态类加载/保存设置的配置,但是配置应该是一个的对象的,因此可以通过左右操纵等。     公共类MyConfiguration     {       公共常量字符串DefaultConfigPath =./config.xml;

The Problem with static that you may be having is that it means different things in .NET and say, C++. Static basically means it's accessible on the class itself. As for it's acceptability id say it's more of something you'd use to do non-instance specific operations on a class. Or just general things like Math.Abs(...). What you should use for a global config is probably a statically accessed property for holding the current/active configuration. Also maybe some static classes for loading/saving setting the config, however the config should be an Object so it can be passed around manipulated, etc. public class MyConfiguration { public const string DefaultConfigPath = "./config.xml";

  protected static MyConfiguration _current;
  public static MyConfiguration Current
  {
    get
    {
      if (_current == null)
        Load(DefaultConfigPath);
      return _current;
    }
  }

  public static MyConfiguration Load(string path)
  {
    // Do your loading here
    _current = loadedConfig;
    return loadedConfig; 
  }

  // Static save function

  //*********** Non-Static Members *********//

  public string MyVariable { get; set; }
  // etc..
}

(2)控制器/硬件

您也许应该考虑一个被动的做法, IObserver<> 的IObservable<> ,它的一部分的href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx" rel="nofollow">无框架(RX)的

You should probably look into a reactive approach, IObserver<> or IObservable<>, it's part of the Reactive Framework (Rx).

另一种方法是使用一个线程池来安排您的投票任务,如果你有很多硬件的游泳池,你可能会得到大量的线程。使用任何一种的线程的学习了很多关于它之前,请确保。这很容易犯错误,你甚至不知道。 这本书是一个外观极好来源,并会教你很多。

Another approach is using a ThreadPool to schedule your polling tasks, as you may get a large number of threads if you have a lot of hardware to pool. Please make sure before using any kind of Threading to learn a lot about it. It's very easy to make mistakes you may not even realize. This Book is an excelent source and will teach you lots.

无论哪种方式,你或许应该建立服务(只是一个名字真)来管理你的硬件,负责收集有关服务(本质上是一个典范模式)的信息。从那里的中央控制器可以使用它们来访问服务的数据保持程序逻辑控制器中,并在硬件逻辑

Either way you should probably build services (just a name really) for managing your hardware which are responsible for collecting information about a service (essentially a model-pattern). From there your central controller can use them to access the data keeping the program logic in the controller, and the hardware logic in the service.

(3)全局配置

我可能已经触及点#1这个问题,但通常这就是我们去哪里,如果你发现自己打字太多了,你可以随时把它救出来假设 .Instance 是一个对象。

I may have touched this subject in point #1 but generally that's where we go, if you find yourself typing too much you can always pull it out of there assuming the .Instance is an object.

MyConfiguration cfg = MyConfiguration.Current
cfg.Foo // etc...

(4)监听数据

同样的反应框架可以帮助你,或者你可以建立一个事件驱动模型使用触发器传入的数据。这将确保你不会阻塞,直到数据是在一个线程,它可以大大降低应用程序的复杂性。

Again the reactive framework could help you out, or you could build up an event-driven model that uses triggers for incoming data. This will make sure you're not blocking on a thread till data comes in. It can reduce the complexity of your application greatly.

这篇关于重构辛格尔顿过度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆