需要设计模式建议

Need Design Pattern Suggestion

我需要帮助来美化这段代码:) definesAction 方法将根据参数调用 Class。考虑到 Class 是相似的,有一些方法可以概括这段代码。 提前致谢

主要Class

def defineAction(args):

    if args.classabc is not None:
        for host in config.getList('ABC', 'hosts'):
            class_abc = ClassABC(config.getConfigs('ABC', host), args.version[0], user, password)
            class_abc.action(args.classabc)

    if args.classxyz is not None:
        for host in config.getList('XYZ', 'hosts'):
            class_xyz = ClassXYZ(config.getConfigs('XYZ', host), args.version[0], user, password)
            class_xyz.action(args.classxyz)

    # ...

def main():

    parser.add_argument('--classabc', choices=['cmd'])
    parser.add_argument('--classxyz', choices=['cmd'])
    # ...
    args = parser.parse_args()
    defineAction(args)

亚Class亚

class ClassABC:
    def __init__(self, configs, user, password):
        self.hostConfigs = configs['host']
        self.host_username = user
        self.host_password = password

    def a_method(self):
        # This Method is equal in all subclasses
    def b_method(self):
        # This Method is different all subclasses

    def action(self, action):
        self.a_method()
        self.b_method()

        if action == 'cmd':
            self.execute_cmd()

配置文件

[ABC]
hosts=abc_host1
var_abc=value1

[XYZ]
hosts=xyz_host1,xyz_host2
var_xyz=value2

我假设这些开关是互斥的(在这种情况下你真的想使用 mutually exclusive argument group)。

您希望 argparser 操作设置 class。如果您的命令行开关不需要任何参数,那么我会在这里使用 action="store_const"

parser.add_argument(
    '--classabc', dest="class_", const=ClassABC,
    action="store_const")
parser.add_argument(
    '--classxyz', dest="class_", const=ClassXYZ,
    action="store_const")

在解析时,当使用一个或另一个开关时,上述操作将 args.class_ 设置为 ClassABCClassXYZ。给 classes 一个 class 方法或一个属性来确定要查看的配置部分,不要在其他任何地方硬编码这些名称。

例如,如果两个 class 都有一个 config_section 属性,(ClassABC 设置为 'ABC',[=23= 设置为 'XYZ' ]), 然后你可以在你的循环创建实例中使用该属性:

if args.class_:
    for host in config.getList(class_.config_section, 'hosts'):
        instance = args.class_(config.getConfig(class_.config_section, host), ...)

想法是不根据 args 属性进行切换,您可以将其留给 argparse,因为它已经为您确定了不同的选项。

如果两个命令行开关都需要额外的参数,则创建一个自定义 Action subclass:

class StoreClassAction(argparse.Action):
    def __call__(self, parser, namespace, values, **kwargs):
        setattr(namespace, self.dest, (self.const, values)

然后将其用作:

parser.add_argument(
    '--classabc', dest="class_", choices=['cmd'], const=ClassABC,
    action=StoreClassAction)
parser.add_argument(
    '--classxyz', dest="class_", choices=['cmd'], const=ClassXYZ,
     action=StoreClassAction)

现在 args.class_ 参数设置为 (classobject, argumentvalue),因此您可以使用:

if args.class_:
    cls, action = args.class_
    for host in config.getList(cls.config_section, 'hosts'):
        instance = args.class_(config.getConfig(cls.config_section, host), ...)
        instance.action(action)