V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  程序员

试了试简单工厂模式代码,懂了这个设计模式,却产生了新的疑惑

  •  
  •   amiwrong123 · 2019-08-17 21:33:35 +08:00 · 2959 次点击
    这是一个创建于 1685 天前的主题,其中的信息可能已经有所发展或是发生改变。

    参考了博客 https://www.jianshu.com/p/e55fbddc071c 考虑此设计模式中有产品类,工厂类和测试类。 首先产品类在 other 包中:

    package other;
    
    public abstract class Product{
        public abstract void Show();
    }
    //具体产品类 A
    class  ProductA extends  Product{
    
        @Override
        public void Show() {
            System.out.println("生产出了产品 A");
        }
    }
    
    //具体产品类 B
    class  ProductB extends  Product{
    
        @Override
        public void Show() {
            System.out.println("生产出了产品 C");
        }
    }
    
    //具体产品类 C
    class  ProductC extends  Product{
    
        @Override
        public void Show() {
            System.out.println("生产出了产品 C");
        }
    }
    

    工厂类在 other 包中:

    package other;
    
    public class Factory {
        public static Product Manufacture(String ProductName){
    //工厂类里用 switch 语句控制生产哪种商品;
    //使用者只需要调用工厂类的静态方法就可以实现产品类的实例化。
            switch (ProductName){
                case "A":
                    return new ProductA();
    
                case "B":
                    return new ProductB();
    
                case "C":
                    return new ProductC();
    
                default:
                    return null;
    
            }
        }
    }
    
    

    最后是测试类,在默认包中:

    //工厂产品生产流程
    import other.Factory;
    
    public class SimpleFactoryPattern {
        public static void main(String[] args){
            Factory mFactory = new Factory();
    
            //客户要产品 A
            try {
    //调用工厂类的静态方法 & 传入不同参数从而创建产品实例
                mFactory.Manufacture("A").Show();
            }catch (NullPointerException e){
                System.out.println("没有这一类产品");
            }
    
            //客户要产品 B
            try {
                mFactory.Manufacture("B").Show();
            }catch (NullPointerException e){
                System.out.println("没有这一类产品");
            }
    
            //客户要产品 C
            try {
                mFactory.Manufacture("C").Show();
            }catch (NullPointerException e){
                System.out.println("没有这一类产品");
            }
    
            //客户要产品 D
            try {
                mFactory.Manufacture("D").Show();
            }catch (NullPointerException e){
                System.out.println("没有这一类产品");
            }
        }
    }
    

    疑问 1.Product 文件中,如果 Product 抽象类没有加 public,那么测试类的每个Show()处都会报错 cant access show() in other.Product.然后这里我加上了 public 就不会报这个错了。但为什么测试类不需要加上import other.Product呢,即使我加上,idea 也告诉我说,导入的这个Product从来没被用过?

    疑问 2.现在的代码能运行,但每个Show()处都会报警告,说调用 show 可能引发空指针异常。我以为把工厂类的 default 行为改了改成return new ProductC();就不会报这个警告了。但还是报这个警告,为啥啊?

    第 1 条附言  ·  2019-08-17 23:15:53 +08:00
    疑问 2 解决了,好像真是 idea 反应慢,default 行为改了就好了,不会报警告了。
    12 条回复    2019-08-17 23:30:21 +08:00
    v2overflow
        1
    v2overflow  
       2019-08-17 22:06:50 +08:00
    2,没 break 吧
    amiwrong123
        2
    amiwrong123  
    OP
       2019-08-17 22:14:59 +08:00
    @v2overflow
    你说 switch case 啊,因为每个分支都有 return,所以不用加 break,加在后面也执行不到。
    ywcjxf1515
        3
    ywcjxf1515  
       2019-08-17 22:18:10 +08:00 via iPad
    mFactory.Manufacture("XXX")的结果是,父类引用指向子类对象,后面 show 调用的是父类的方法,方法内容由子类定,父类的 show 方法是默认的包可见性,就不能 access 父亲的 show 方法。你可以向下转型,子类引用指向子类对象,这样 show 方法是子类的 show 方法,可见性是 public。
    iEverX
        4
    iEverX  
       2019-08-17 22:20:00 +08:00
    1. 因为确实没用到。Java 从来不要求使用了方法就需要 import
    2. 应该没问题,ide 反应慢吧
    amiwrong123
        5
    amiwrong123  
    OP
       2019-08-17 22:31:42 +08:00
    @ywcjxf1515
    等一下,父类的 show 方法是 public 的啊,不是默认包可见啊。我比较纳闷的是,为毛不加上 import other.Product,它还能调用 show 呢。。
    而且我发现报错信息 cant access show() in other.Product 这句里面,为毛报错信息都知道 Product 都知道这个 Product 在 other 包而不是其他包中呢。。。
    amiwrong123
        6
    amiwrong123  
    OP
       2019-08-17 22:34:11 +08:00
    @iEverX
    1.你说的这点,勉强我可以接受,但我还没在书中找到证实。。
    2.应该不是 idea 反应慢吧,不然它这反射弧也太长了吧。。。
    ywcjxf1515
        8
    ywcjxf1515  
       2019-08-17 22:55:23 +08:00 via iPad
    @amiwrong123 疑问 1 里你补加的 public 是在类上的吧,没加之前是默认的包可见性,方法也跟着是。
    因为你调用这个 show 方法时,没有出现父类,就不用导入。你可以写一个工厂类,工类类方法返回一个 ArrayList,调用这个工厂类方法,同样不用引用变量接着,直接调用 ArrayList 的方法,你会发现同样不用导入 ArrayList。
    amiwrong123
        9
    amiwrong123  
    OP
       2019-08-17 22:58:58 +08:00
    @iEverX
    看到了这句 You may live without any import statement when you always specify the full qualified name of classes。
    现在我的理解是:编译器知道 mFactory.Manufacture("XXX")的返回值类型是 other.Product,而且编译器不仅知道返回值类型,而且它还不用我告诉它这个类型(指在测试类中加入 import other.Product ),就算我加了 import other.Product,它也会对我说:“我不用你的,我自己知道!”(报警告,此 other.Product 从未被用过)
    amiwrong123
        10
    amiwrong123  
    OP
       2019-08-17 23:12:04 +08:00
    @ywcjxf1515
    关于访问权限我懂了,先是看类的访问权限,再是看类里各个方法的访问权限。两个都可以才可以访问到。
    关于直接调用 show,直接原因应该就是因为我没有用引用去接产品类对象,所以可以直接调用。但总感觉没理解到位==
    amiwrong123
        11
    amiwrong123  
    OP
       2019-08-17 23:16:59 +08:00
    @iEverX
    疑问 2 解决,就是因为 default 返回 null 的原因。真的反应慢。
    iEverX
        12
    iEverX  
       2019-08-17 23:30:21 +08:00
    import other.Product 只是把名字 Product 当作 other.Product。既然没有用 Product 这个名字,当然就不用 import
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3019 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 11:04 · PVG 19:04 · LAX 04:04 · JFK 07:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.