我是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
已添加。为了确保新客户端接收到Child
,Adult
,Pensioner
或PersonFactoryWithInfant
的任何对象都是合适的,新类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原则。