简体   繁体   English

在基类中实现工厂时,从派生类封装工厂方法的正确方法是什么?

[英]What is the correct way to encapsulate factory methods from derived classes when implementing factory in base class?

I am trying to create simple class with ability to register derived classes for creation from base class. 我正在尝试创建具有注册派生类以从基类进行创建的能力的简单类。 However I cannot find a good way to encapsulate this functionality from descendants. 但是,我找不到从后代封装此功能的好方法。

Class variables looks for me a bad idea because they available everywhere in inheritance chain. 类变量对我来说是个坏主意,因为它们在继承链中随处可见。 So I try do something with class instance variables. 因此,我尝试对类实例变量进行操作。 Perfectly it will be that all class methods will be inaccessible except register_as 完美的是,除了register_as之外,所有类方法都将不可访问

class A
  @registered = {}
  class << self
    def register_as(name)
      A.registered[name] = self
    end

    def known
      A.registered
    end

    protected
    attr_accessor :registered
  end

  def helpful_method
  end

end

class B < A
  class << self
    def reg_trash
      A.registered[:trash] = :trash
    end
  end
  B.register_as :b
end

B.reg_trash
p A.known

However registered is still accessible from B class. 但是仍然可以从B类访问已注册。 Currently looks like the only one possible option is to split A class to dedicated Factory class and A class will hold only helpful instance methods. 当前,似乎唯一可行的选择是将A类拆分为专用的Factory类,并且A类仅包含有用的实例方法。 Maybe it is possible to do something via .inherited and .undef_method, isn't it? 也许可以通过.inherited和.undef_method进行某些操作,不是吗?

Maybe it is possible to do something via .inherited and .undef_method, isn't it? 也许可以通过.inherited和.undef_method进行某些操作,不是吗?

Yes, it is possible. 对的,这是可能的。 But the idea smells, as for me - you're going to break substitutability. 但就我而言,这个主意很难闻-您将打破可替代性。

If you don't want the "derived" classes to inherit the behavior of the parent, why do you use inheritance at all? 如果您不希望“派生”类继承父代的行为,那么为什么要使用继承呢? Try composition instead and mix in only the behavior you need. 请尝试合成,并仅混合所需的行为。 For example, something like this could work ( very dirty example, but I hope you got the idea): 例如,类似这样的方法可能会起作用( 非常肮脏的示例,但我希望您有个主意):

class A
  module Registry
    def register_as(name)
      A.register_as(name, self)
    end
  end

  @registered = {}

  def self.register_as(name, klass)
    @registered[name] = klass
  end

  def self.known
    @registered
  end
end

class B
  extend A::Registry
  register_as :b  
end

class C
  extend A::Registry
  register_as :c
end

A.known # => {:b => B, :c => C}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM