以下代码可以运行,但是我的实现违反了SOLID原则。我希望有人可以帮助我重新设计代码,使其遵循SOLID原则,尤其是避免使用instanceof
。
我有一个父类Parent
和三个子类:Element
,Container
和Wrapper
。
Element
仅包含一个整数,如数学标量。
Container
有一个父数组Parent[] contents
,它可以是任何子类,例如数学向量。它可以是标量(元素)的向量,向量(容器)的向量或函数(包装器)的向量。
Wrapper
有一个接口Function
,程序员可以为每个包装程序定义一个唯一的方法。例如,一个包装器可能包含一个将元素平方的函数,而另一个包装器可能包含一个在两个容器之间获取点积的函数。
Wrapper
用两个通用类型Wrapper<Domain extends Parent,Range extends Parent>
进行参数化,它们表示输入类型Domain和输出类型Range。
当我尝试访问Parent[] contents
类中的Container
数组时,出现了我的问题。由于内容可以是任何子类,并且每个子类对其add
方法都有不同的定义,所以我发现自己不得不使用instanceof,这违反了SOLID原则。
如何更改代码的结构?
public class Parent {
public Parent add(Parent p){return null;}
}
public class Element extends Parent{
protected int value;
public void set(int x){ value=x; }
public int get(){ return value; }
public Element(){ set(0); }
public Element(int x){ set(x); }
@Override
public Parent add(Parent p){
if (p instanceof Element){
Element e = (Element) p;
return add(e);
}
else if (p instanceof Container){
Container c = (Container) p;
return add(c);
}
else return null;
}
public Element add(Element e){ return new Element( get()+e.get()); }
public Container add(Container c){ return c.add(this); }
}
///I would prefer for this class to be parameterized Container<Type>, but I run into the problem of instantiating generic arrays
public class Container extends Parent{
protected Parent[] contents;
public int length(){ return contents.length; }
public Container(int x){ contents = new Parent[x]; }
public void set(int k, Parent p){ contents[k]=p; }
public Parent get(int k){ return contents[k]; }
///Have to use instanceof to determine which type of output it will be
public Parent sum(){
Parent p;
if(get(0) instanceof Element)
p = new Element();
else if (get(0) instanceof Wrapper)
p = new Wrapper();
else p = new Parent();
for(int k=0;k<contents.length;++k)
p = p.add(contents[k]);
return p;
}
///Have to use instanceof to distinguish which add to use
@Override
public Parent add(Parent p){
if (p instanceof Element){
Element e = (Element) p;
return add(e);
}
else if (p instanceof Container){
Container c = (Container) p;
return add(c);
}
else return null;
}
///adds element to the first entry in the container
public Container add(Element e){
Container out = new Container(contents.length);
for(int k=0;k<contents.length;++k)
out.set(k, contents[k]);
out.set(0, out.get(0).add(e));
return out;
}
///adds component by component
public Container add(Container c){
int minLength;
if(c.length() < contents.length)
minLength = c.length();
else minLength = contents.length;
Container out = new Container(minLength);
for(int k=0;k<minLength;++k)
out.set(k, contents[k].add( c.get(k) ));
return out;
}
}
public interface Function <Domain extends Parent, Range extends Parent> {
public Range of(Domain point);
}
public class ZeroFunction<Domain extends Parent,Range extends Parent> implements Function<Domain,Range>{
@Override
public Range of(Domain point) {
return (Range) new Element();
}
}
public class Wrapper<Domain extends Parent, Range extends Parent> extends Parent{
protected Function<Domain,Range> function;
public Wrapper(){ function = new ZeroFunction<Domain,Range>(); }
public Wrapper(Function<Domain,Range> x) { function = x; }
public Range of(Domain t){ return function.of(t); }
@Override
public Parent add(Parent p){
if (p instanceof Wrapper)
return add( (Wrapper) p);
else return null;
}
public Wrapper<Domain,Range> add(final Wrapper<Domain,Range> w){
return new Wrapper<Domain,Range>( new Function<Domain,Range>(){
public Range of(Domain point){
try{
Range term = function.of(point);
Range summand = w.of(point);
Range sum = (Range) term.add(summand);
return sum;
} catch(Exception e){
e.printStackTrace();
return null;
}
}
});
}
}
public class Main {
public static void main(String[] args){
Wrapper<Container, Element> wrapper1 = new Wrapper<Container, Element>(new Function<Container, Element>() {
@Override
public Element of(Container c) {
return (Element) c.sum();
}
});
Wrapper<Container, Element> wrapper2 = new Wrapper<Container, Element>(new Function<Container, Element>() {
@Override
public Element of(Container c) {
return (Element) c.sum();
}
});
Container wContainer = new Container(2);
wContainer.set(0, wrapper1);
wContainer.set(1, wrapper2);
Wrapper<Container,Element> wrapper3 = (Wrapper<Container,Element>) wContainer.sum();
Container eContainer = new Container(2);
eContainer.set(0, new Element(1));
eContainer.set(1, new Element(2));
Element solution = wrapper3.of(eContainer);
System.out.println(solution.get());
}
}