我正在寻找一个简单问题的设计模式。这是一个简化版本。
class Animal{...}
class Dog extends Animal{...}
class Cat extends Animal{...}
... // so on, 3 other classes as of now
我有一个静态方法(实际上是通过网络服务公开但是它的同义词),它采用id
并返回一只动物。
如果返回cat
,那么使用cat
对象的其他团队会生成CatReport。如果狗,然后狗报告(他们可以用它做任何事情)。显然Cat& Dog 具有不同的属性。除了动物之外,Cat
和Dog
没有任何共同之处。所以拨打下面的电话是不够的,因为我需要精确的类型:
public static Animal getAnimal(int id){}
不够,因为animal
不包含精确类型可以给我的所有信息。
解决这个问题的最佳方法是什么?
PS:在Scala
中,我只是对对象进行模式匹配。这很好地解决了这个问题。
我的一个解决方案是:拨打一个回复enum
的电话,表示id
对应的内容。然后分别打电话给每个人:
public static AnimalType getAnimalType(int id){}
public static Cat getCat(int id){}
public static Dog getDog(int id){}
....
但这很麻烦。
答案 0 :(得分:2)
在Java等语言中,您可以使用Visitor
模式模拟模式匹配行为。
您可以通过以下几个步骤执行此操作:
Animal
方法accept
Animal
并提供相同的实现,如下面的小例子所示。Visitor
并为其提供实现。这个classe将允许您在类上模拟一些模式匹配。这里有一个小例子:
public interface Animal {
public void accept(AnimalVisitor v);
}
public class Dog extends Animal {
public void accept(AnimalVisitor v) {
v.visit(this);
}
}
public class Cat extends Animal {
public void accdept(AnimalVistior v) {
v.visit(this);
}
}
public interface AnimalVisitor {
public void visit(Dog d);
public void visit(Cat c);
}
public class PrintAnimal implements AnimalVisitor {
public void visit(Dog d) {
System.out.println("Dog");
}
public void visit(Cat c) {
System.out.println("Cat");
}
}
Visitor
模式是解决问题的优雅方式,也避免了if (x instance of bar)
在一个函数中的积累。使用此模式,您的代码将更易读,更容易扩展。
相应的Scala代码,让我知道我的答案:
abstract class Animal {}
case class Dog() extends Animal
case class Cat() extends Animal
object Animal {
def printAnimal(a : Animal) = a match {
case x : Dog => "Dog"
case x : Cat => "Cat"
case _ => "Unknown"
}
def main(args : Array[String]) = {
println(printAnimal(Dog()))
}
}
答案 1 :(得分:0)
嗯,我没有看到任何真正优雅的解决方案,但你可以使用这种代码创建一种报告工厂
public Report getCorrespondingReport(Animal animal){
if(animal instanceof Dog) return new DogReport();
if(animal instanceof Cat) return new CatReport();
...
...或者您可以制作通用报告并使用反射来检查您的Animal实例并按照一般规则生成您的报告,但它可能不可行。
答案 2 :(得分:-1)
如果我正确理解了这个问题,你想要调用关于你所拥有的对象类型的方法的正确实现。因此,如果动物是猫,如果您有类似下面的代码,则应从Cat类调用生成报告方法
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
首先,正如你所说,
显然Cat&狗有不同的属性。猫与狗没有 除了他们是动物之外的任何其他共同点。
由于子类没有任何通用功能,因此将Animal定义为接口而不是如下所示的类
interface Animal{
public void generateReport();
}
像这样创造猫与狗
class Cat implements Animal{
//define cat specific attributes here
public void generateReport(){
//your logic to generate cat report
}
}
class Dog implements Animal{
//define dog specific attributes here
public void generateReport(){
//your logic to generate dog report
}
}
由于在接口中定义了generateReport()方法,因此实现接口的所有类都必须具有generateReport()。
所以当你打这样的电话时,
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
将调用底层对象的方法。
如果你只想知道动物对象是指什么(从getAnimal方法返回,即Cat或Dog),你可以像下面那样检查
class Animal{
}
class Dog extends Animal{
public String dogName = "Dog1";
}
class Cat extends Animal{
public String catName = "Cat1";
}
public class HelloWorld{
public static void main(String []args){
//call getAnimal and get the object instead of following line
Animal animal = new Cat();
if ( animal instanceof Cat ){
//cast Animal to Cat
Cat cat = (Cat) animal;
System.out.println(cat.catName);
}else if ( animal instanceof Dog ){
//cast Animal to Dog
Dog dog = (Dog) animal;
System.out.println(dog.dogName);
}
}
}