类似模式匹配的行为
Pattern Matching like behavior
我正在为我的简单问题寻找设计模式。这是一个简化版本。
class Animal{...}
class Dog extends Animal{...}
class Cat extends Animal{...}
... // so on, 3 other classes as of now
我有一个静态方法(实际上是通过网络服务公开的,但它是同义词),它需要一个 id
和 returns 一个动物。
如果返回 cat
,则 其他团队 使用 cat
对象生成 CatReport。如果是狗,则狗报告(他们可以将其用于任何事情)。显然猫狗有不同的属性。 Cat
和 Dog
除了都是动物之外没有任何其他共同点。所以像下面这样打电话是不够的,因为我需要精确的类型:
public static Animal getAnimal(int id){}
不够,因为 animal
没有包含精确类型所能提供的所有信息。
处理这个问题的最佳方法是什么?
PS:在Scala
中,我只会对对象进行模式匹配。这样就优雅的解决了问题
我的一个解决方案是:调用 returns 一个 enum
表示 id
对应的内容。然后分别调用每个:
public static AnimalType getAnimalType(int id){}
public static Cat getCat(int id){}
public static Dog getDog(int id){}
....
但这很麻烦。
如果我对问题的理解正确,你想调用关于你拥有的对象类型的方法的正确实现。因此,如果动物是猫,如果您有如下代码
,则应从 Cat class 调用生成报告方法
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
首先正如你所说,
Obviously Cat & Dog have different attributes. Cat and Dog dont have
anything else in common apart from the fact that they are Animals.
由于 subclasses 没有任何共同的功能,将 Animal 定义为接口而不是像下面给出的 class
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()方法,所有实现该接口的classes都必须有generateReport()。
所以当你这样打电话时,
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
底层对象的方法将被调用。
如果你只是想知道动物对象指的是什么(从 getAnimal 方法返回,即猫或狗),你可以像下面这样检查
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);
}
}
}
在像 Java 这样的语言中,您可以使用 Visitor
模式模拟模式匹配行为。
您可以分几步完成:
- 用
accept
方法定义一个接口 Animal
表示 Animal
- 向
Animal
添加一些子 类 并提供与下面我的小示例相同的实现。
- 定义一个接口
Visitor
并给它一个实现。该类将允许您在 类. 上模拟一些模式匹配
这里有一个小例子:
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()))
}
}
好吧,我没有看到任何真正优雅的解决方案,但你可以用这种代码创建一种报表工厂
public Report getCorrespondingReport(Animal animal){
if(animal instanceof Dog) return new DogReport();
if(animal instanceof Cat) return new CatReport();
...
...或者您可以制作一个通用报告并使用反射来检查您的 Animal 实例并按照一般规则生成您的报告,但这可能不可行。
我正在为我的简单问题寻找设计模式。这是一个简化版本。
class Animal{...}
class Dog extends Animal{...}
class Cat extends Animal{...}
... // so on, 3 other classes as of now
我有一个静态方法(实际上是通过网络服务公开的,但它是同义词),它需要一个 id
和 returns 一个动物。
如果返回 cat
,则 其他团队 使用 cat
对象生成 CatReport。如果是狗,则狗报告(他们可以将其用于任何事情)。显然猫狗有不同的属性。 Cat
和 Dog
除了都是动物之外没有任何其他共同点。所以像下面这样打电话是不够的,因为我需要精确的类型:
public static Animal getAnimal(int id){}
不够,因为 animal
没有包含精确类型所能提供的所有信息。
处理这个问题的最佳方法是什么?
PS:在Scala
中,我只会对对象进行模式匹配。这样就优雅的解决了问题
我的一个解决方案是:调用 returns 一个 enum
表示 id
对应的内容。然后分别调用每个:
public static AnimalType getAnimalType(int id){}
public static Cat getCat(int id){}
public static Dog getDog(int id){}
....
但这很麻烦。
如果我对问题的理解正确,你想调用关于你拥有的对象类型的方法的正确实现。因此,如果动物是猫,如果您有如下代码
,则应从 Cat class 调用生成报告方法public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
首先正如你所说,
Obviously Cat & Dog have different attributes. Cat and Dog dont have anything else in common apart from the fact that they are Animals.
由于 subclasses 没有任何共同的功能,将 Animal 定义为接口而不是像下面给出的 class
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()方法,所有实现该接口的classes都必须有generateReport()。
所以当你这样打电话时,
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
底层对象的方法将被调用。
如果你只是想知道动物对象指的是什么(从 getAnimal 方法返回,即猫或狗),你可以像下面这样检查
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);
}
}
}
在像 Java 这样的语言中,您可以使用 Visitor
模式模拟模式匹配行为。
您可以分几步完成:
- 用
accept
方法定义一个接口Animal
表示 Animal - 向
Animal
添加一些子 类 并提供与下面我的小示例相同的实现。 - 定义一个接口
Visitor
并给它一个实现。该类将允许您在 类. 上模拟一些模式匹配
这里有一个小例子:
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()))
}
}
好吧,我没有看到任何真正优雅的解决方案,但你可以用这种代码创建一种报表工厂
public Report getCorrespondingReport(Animal animal){
if(animal instanceof Dog) return new DogReport();
if(animal instanceof Cat) return new CatReport();
...
...或者您可以制作一个通用报告并使用反射来检查您的 Animal 实例并按照一般规则生成您的报告,但这可能不可行。