替代全局变量或单例

问题描述 投票:1回答:2

我在各个地方都读到全局变量充其量是一种代码味道,最好避免。目前,我正在将基于大型函数的PS脚本重构为类,并考虑使用Singleton。用例是一个大型数据结构,需要从许多不同的类和模块中进行引用。然后我发现了this,这似乎也表明,单例也是一个坏主意。

因此,在PS 5.1中创建单个数据结构的正确方法是什么?该方法需要被许多类引用并被其中一些类修改?可能相关的事实是我不需要此线程安全的事实。根据定义,队列将以非常线性的方式进行处理。

FWIW,我到达了所引用的链接,以查找有关单例和继承的信息,因为我的单例只是行为非常相似的许多类之一,我从单例开始,其中包含下一个类的集合,每个包含下一个类的集合,以创建分层队列。我希望有一个基类来处理所有通用队列管理,然后将其扩展为每个类的不同功能。除了使第一个扩展类成为单例外,其他方法都很棒。这似乎是不可能的,对吗?

编辑:或者,使用通用列表属性方法中的此嵌套类是否可以从子对象中识别父对象?这就是我处理基于功能的版本的方式。全局[XML]变量构成了数据结构,我可以逐步遍历该结构,使用.SelectNode()填充变量以向下传递至下一个函数,并使用.Parent从较高位置获取信息,尤其是从数据结构的根。

编辑:由于我现在似乎无法在此处粘贴代码,因此我在GitHub上有一些代码。 Singleton进入的示例在121行,我需要验证是否还没有完成同一任务的其他示例,因此我可以跳过最后一个实例。这是删除各种Autodesk软件通用组件的概念证明,该软件以非常特殊的方式进行管理。因此,我希望能够安装任何程序(程序包)组合并按计划进行卸载,并确保最后一个具有共享组件卸载功能的程序包是将其卸载的程序包。为了不中断其他相关程序,请在最后一次卸载发生之前。希望这是有道理的。 Autodesk的安装让人痛苦不堪。如果您不必与他们打交道,请认为自己很幸运。 :)

powershell singleton global-variables
2个回答
0
投票

如评论中所述,链接到的代码中的任何内容都不需要单例。

如果要在ProcessQueue与相关Task实例之间保留父子关系,可以从结构上解决。

仅需要在ProcessQueue构造函数中注入Task实例:

class ProcessQueue
{
  hidden [System.Collections.Generic.List[object]]$Queue = [System.Collections.Generic.List[object]]::New()
}

class Task
{
  [ProcessQueue]$Parent
  [string]$Id
  Task([string]$id, [ProcessQueue]$parent)
  {
    $this.Parent = $parent
    $this.Id = $id
  }
}

实例化对象层次结构时:

$myQueue = [ProcessQueue]::new()
$myQueue.Add([Task]@{ Id = "id"; Parent = $myQueue})

...或重构ProcessQueue.Add()以构造任务:

class ProcessQueue
{
  [Task] Add([string]$Id){
    $newTask = [Task]::new($Id,$this)
    $Queue.Add($newTask)
    return $newTask
  }
}

此时,您仅将ProcessQueue.Add()用作[Task]构造函数的代理:

$newTask = $myQueue.Add($id)
$newTask.DisplayName = "Display name goes here"

下次您需要从单个Task实例中搜索相关任务时,只需执行以下操作:

$relatedTasks = $task.Parent.Find($whatever)

0
投票

补充Mathias R. Jessen's helpful answer-可能是对您问题的最佳解决方案-回答您的原始问题:

因此,在PS 5.1中创建一个需要由许多类引用并由其中一些类修改且无需担心线程安全的单一数据结构的正确方法是什么?

  • 避免使用global variables的主要原因是它们是session-global,这意味着执行after的代码也会看到那些变量,这些变量可以副作用。

  • 您无法在PowerShell中实现真正的单例,因为PowerShell类不支持访问修饰符;值得注意的是,您不能使构造函数private(非公共),您只能使用hidden关键字“隐藏”它,但是只能使它<,而仍是accessible] >。

  • 您可以使用以下技术来

    近似

    单例,该技术本身模拟static class
  • (PowerShell也不支持,因为static关键字仅在类成员,而不是整个班级。]

    一个简单的例子:

    class AlmostAStaticClass { hidden AlmostAStaticClass() { Throw "Instantation not supported; use only static members." } static [string] $Message # static property static [string] DoSomething() { return ([AlmostAStaticClass]::Message + '!') } }

[AlmostAStaticClass]::<member>(例如,[AlmostAStaticClass]::Message = 'hi')现在可以在其中定义了AlmostAStaticClass的范围中使用[[和所有后代范围(但是,

not

全局可用,除非定义范围恰好是全球性的)。如果需要访问类跨模块边界,则可以将其作为

parameter

(作为类型文字)传递;注意,您仍然需要::来访问(总是静态的)成员;例如。,& { param($staticClass) $staticClass::DoSomething() } ([AlmostAStaticClass])
© www.soinside.com 2019 - 2024. All rights reserved.