java - 关于固定类双重调度的问题

标签 java oop design-patterns

我有 3 个类(class):**Parent**、**Child1** 和 **Child2**。 Child1 和 Child 2 都扩展了 Parent 并且它们**不能**被修改。

有一个Action类定义如下:

public class Action {
    public static void perform(Parent p) {
        if (p instanceof Child1) {
            action((Child1)p);
        }
        else if (p instanceof Child2) {
            action((Child2)p);
        }
        else {
            action(p);
        }
    }

    private static void action(Parent p) {
        ...
    }
    private static void action(Child1 c1) {
        ...
    }
    private static void action(Child2 c2) {
        ...
    }
}


Parent p = new Child1();
Action.perform(p);

如果没有 instanceof 运算符,是否有任何方法可以获得与上述相同的行为?

======
(修改)

PS:Action.perform给定的参数类型是Parent,但是它的值是Child1,所以我觉得方法重载不行....

最佳答案

这里有两个 C# 解决方案,一个基本相同但更简洁,适合子类数量较少的情况。

public class Parent
{
}

public class Child1 : Parent
{
}

public class Child2 : Parent
{
}

public class Action
{
    private static Dictionary<Type, Action<Parent>> _d = new Dictionary<Type, Action<Parent>>()
                                                    {
                                                        {typeof(Child1), p=>action((Child1)p)},
                                                        {typeof(Child2), p=>action((Child2)p)},
                                                        {typeof(Parent), p=>action(p)}
                                                    };
    public static void perform(Parent p)
    {
        _d[p.GetType()](p);
    }

    private static void action(Parent p)
    {

    }

    private static void action(Child1 c1)
    {

    }
    private static void action(Child2 c2)
    {

    }
}



class Program
{
    static void Main(string[] args)
    {
        Parent p = new Child1();
        Action.perform(p);
    }
}`enter code here`

无论如何,它打破了 OCP,但比使用反射更快。这个不破坏OCP但使用反射来填充字典:

public class Action
        {
            private static Dictionary<Type, Action<Parent>> _d;

            static Action()
            {
                Initialize();
            }

            private static void Initialize()
            {
                var methods = typeof(Action)
                    .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                    .Where(IsActionMethod)
                    .ToList();

                _d = methods.ToDictionary(m => m.GetParameters().First().ParameterType,
                                          m => (Action<Parent>) (x => m.Invoke(null, new[] {x})));
            }

            private static bool IsActionMethod(MethodInfo methodInfo)
            {
                var parameters = methodInfo.GetParameters();

                return parameters.Length == 1
                       && typeof(Parent).IsAssignableFrom(parameters.First().ParameterType)
                       && methodInfo.ReturnType == typeof(void);
            }

            public static void perform(Parent p)
            {
                _d[p.GetType()](p);
            }

            private static void action(Parent p)
            {

            }

            private static void action(Child1 c1)
            {

            }

            private static void action(Child2 c2)
            {

            }
}

关于java - 关于固定类双重调度的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7556892/

相关文章:

java - 如何在流布局中组织对象?

c++ - 避免菱形继承(钻石问题)

java - RSA 使用 Pycrypto OAEP 加密并使用普通旧 Java 解密

java - 为什么hibernate连接所有表,声明这个特定的连接?

oop - 域对象可以与持久化对象相同吗?

oop - 抽象工厂是否引入紧耦合

java - Dozer 5.4 setCustomConverter 在同名但不同类型的字段之间不起作用

java - 寻找使用 ISO 9797-1 算法 3(零售 MAC)计算 Mac 的方法

.net - 实现一个使用规范来确定要创建哪种类型的对象的工厂

用户最爱的SQL数据库设计模式?