我是OOP的新手,正在学习设计模式,所以我写了一些简单的代码来尝试Factory方法,一切似乎都很好,除非我想添加另一个子类型。这是到目前为止的代码:

public interface Person {
  public String getDescription();
}

public class Adult implements Person {
  @Override
  public String getDescription() {
    return "I am an ADULT";
  }
}

public class Child implements Person {
  @Override
  public String getDescription() {
    return "I am a CHILD";
  }
}

public class PersonFactory {
  public Person create(int age) {
    if (age < 18) return new Child();
    return new Adult();
  }
}

public class ClientA {
  public static void main(String[] args) {
    PersonFactory personFactory = new PersonFactory();
    Person person;
    person = personFactory.create(80);
    System.out.println(person.getDescription());
  }
}

如果以后要求改变为包含年龄大于70岁的子类Pensioner,我将必须执行以下任一操作:

if (age > 70) return new Pensioner();行添加到create()类中的PersonFactory方法中,这肯定会破坏开放式封闭原则吗?
或者,如《四个设计模式的帮派》一书中所建议的那样,覆盖参数化的工厂方法以有选择地扩展创作者生产的产品。在这种情况下,我认为这意味着编写一个新类:
public class PersonFactoryWithPensioner extends PersonFactory {
  @Override
  public Person create(int age) {
    if (age > 70) return new Pensioner();
    return super.create(age);
  }
}

现在,这意味着要么必须将所有调用PersonFactory的客户端更改为使用PersonFactoryWithPensioner,要么必须接受新客户端可以调用PersonFactoryWithPensioner而旧客户端可以调用ClientA的请求。年龄大于70岁时,Adult仍将只接收Infant对象。如果稍后再出现在另一个子类上,则情况甚至更糟。 Infant已添加。为了确保新客户端接收到ChildAdultPensionerPersonFactoryWithInfant的任何对象都是合适的,新类PersonFactoryWithPensioner将必须扩展PersonFactory。这可能不对,似乎我可能误解了GoF的建议。

我的问题是:是否有一种方法可以添加新的子类型,而无需更改旧子客户端,又可以通过更改ojit_code代码使其包含新的子类型而又不破坏OCP,又可以将其返回给旧客户端?

抱歉,如果我没有正确发布此信息,这是我第一次在此处发布问题。我已经看过以前针对类似问题的答案,但他们似乎并没有完全解决这个问题。

最佳答案

我认为OCP不会不停地修改任何方法或类。

但是,它建议如果需要进行任何干预,则应该这样做,这样就不必再次修改该代码。

鉴于您稍后可能需要修改PersonFactory,可以创建另一个Factory类来创建PersonFactory类型的对象。尽管这似乎是过度设计的解决方案。

另一个可能的解决方案是PersonFactory从某个动态源加载此规则,例如,使用JSON格式将该规则保存在文件中。
然后使用反射动态创建对象。

像这样的东西:

 private static JSONObject RULES;
   static {
       RULES= JSON.parse(rulesEngine.load());
   }
    public class PersonFactory {
      public Person create(int age) {
        String personToCreate = RULES.get(age);
        Constructor<?> ctor = Class.forName(personToCreate).getConstructor();
        return (Person) ctor.newInstance();
      }
    }

json规则如下所示:
{
  "1":"Child.class",
  "2":"Child.class",
  ...,
  "17":"Child.class",
  "18":"Adult.class",
  ...,
  "69":"Adult.class",
  "70":"Pensioner.class"
}

这样,您就不会违反OCP原则。

10-06 04:57