简体   繁体   English

Java中的工厂类设计问题

[英]Factory class design issue in java

I have two classes 我有两节课

public class PrepaidPackage {

    private String name;
    private String serviceClassID;
    private boolean isTranferable;

    public boolean isTranferable() {
        return isTranferable;
    }
    public void setTranferable(boolean isTranferable) {
        this.isTranferable = isTranferable;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getServiceClassID() {
        return serviceClassID;
    }
    public void setServiceClassID(String serviceClassID) {
        this.serviceClassID = serviceClassID;
    }
}

other class is 其他班级是

public class PostpaidPackage {
    private String name;
    private boolean isTranferable;
    public boolean isTranferable() {
        return isTranferable;
    }
    public void setTranferable(boolean isTranferable) {
        this.isTranferable = isTranferable;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

I want to create a factory class which on base of package type create relevant class. 我想创建一个工厂类,它基于包类型创建相关的类。 But if you look at above clasess they dont have same type of methods and variables. 但是,如果您看上面的分类,它们就没有相同类型的方法和变量。 So please guide how create interface or abstract class for above class? 因此,请指导如何为上述类创建接口或抽象类?

Now factory will return class name Package. 现在工厂将返回类名Package。 Would i able to call methods which are not present in other class. 我可以调用其他类中不存在的方法吗?

Updates 更新

Please suggest if i break my package into two classes like 请建议我是否将我的包裹分成两类

public abstract class MyPackage {
    public abstract PackageSpec getSpec();
    public abstract PackagePrepaidDetails getDetail();
}

Now common attributes will be in PackageSpec and prepaid stuff in packageDetails. 现在,常用属性将位于PackageSpec中,而预付费内容将位于packageDetails中。

Its kind of abstract factory pattern. 它是一种抽象工厂模式。

public class PrepaidPackage extends MyPackage{
    PackageSpec spec;
    public Spec getSpec() {
      spec = new PackageSpec();
      spec.setTranferable(true)
      spec.setName("abc");
      return spec;
    }
    public PackagePrepaidDetails getDetails() {
      details = new PackagePrepaidDetails ();
      details.setServiceClassID(123)
      return details;
    }
}

public class PostpaidPackage extends MyPackage{
    PackageSpec spec;
    public Spec getSpec() {
        spec = new PackageSpec();
        spec.setTranferable(true)
        spec.setName("abc");
        return spec;
    }
}

A quick fix, not an ideal one is to have an interface that represents all the methods in the Prepaid class and leave them unimplemented in the Postpaid. 一种快速解决方法(不是一个理想的解决方法)是使用一个接口来表示Prepaid类中的所有方法,并使它们在Postpaid中未实现。 That will solve the problem in the short term. 这将在短期内解决问题。 I would suggest that you have a relook of the classes and the usages to avoid unimplemented methods in the code. 我建议您重新看一下类和用法,以避免代码中未实现的方法。

Well for an abstract super class you have to group everything common to both : 对于抽象超类,您必须将两者的所有共同点归为一组:

public abstract class MyPackage { // not sure you can call a class just "Package"
    private String name;
    private boolean isTranferable;

    public boolean isTranferable() {
        return isTranferable;
    }
    public void setTranferable(boolean isTranferable) {
        this.isTranferable = isTranferable;
    }
    public String getName() {
       return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

then both inherits from it (the first adds serviceClassID and the second nothing) 然后两者都继承自它(第一个添加serviceClassID ,第二个都不添加)

your factory function will return a MyPackage (or AbstractPackage, whatever), but to access the specific function you'll have to cast after an instanceof test. 您的工厂函数将返回MyPackage(或AbstractPackage,无论如何),但是要访问特定函数,必须在执行instanceof测试后instanceof

I recomment you to have an interface if you don't have already. 如果您还没有界面,我建议您使用它。 You do not neccessarily need it, but it is a good practice if they are so similar: 您不一定需要它,但是如果它们是如此相似,则这是一个好习惯:

public interface Package {
    public boolean isTranferable();
    public void setTranferable(boolean isTranferable);
    public String getName();
    public void setName(String name);
}

Then in your calling code, you have a Package from your factory and: 然后在您的调用代码中,您有一个工厂包装,并且:

Package p = myFactory.nextPackage();    // or something
if (p instanceof PrepaidPackage) {
    PrepaidPackage prepaid = (PrefpaidPackage)p;
    // and do the thing you want
} else if (p instanceof PostpaidPackage) {
    PostpaidPackage postpaid = (PostpaidPackage)p;
    // amd do the other things
}

Thing you are recommended to llok into is the instanceof operator and type casting . 建议您使用的是instanceof运算符和类型转换

Two possible design choices you can make: 您可以做出两种可能的设计选择:

  1. Have the prepaid package extend postpaid package and your factory then returns objects of type postpaid package, the code which calls the factory is then responsible for inspecting the type. 让预付包裹扩展后付包裹,然后您的工厂返回后付包裹类型的对象,然后调用工厂的代码负责检查类型。

  2. Have a package interface which defines all of the methods and have postpaid package define the methods to throw an UnsupportedOperationException (ala the way collections defines some operations as optional.) or return some kind of sentinel value (ie null) 具有定义所有方法的包接口,并具有后付费包定义用于抛出UnsupportedOperationException的方法(以集合将某些操作定义为可选的方式)或返回某种前哨值(即null)

For either of the above you could add another method getType() which returns an enum of the various package types you wish to implement, and this could then be used in the code that accesses the factory objects to determine which methods are available. 对于以上两种情况,您都可以添加另一个方法getType(),该方法返回要实现的各种程序包类型的枚举,然后可以在访问工厂对象的代码中使用它以确定可用的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM