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

2019-08-17 21:33:35 +08:00
 amiwrong123

参考了博客 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();就不会报这个警告了。但还是报这个警告,为啥啊?

2993 次点击
所在节点    程序员
12 条回复
v2overflow
2019-08-17 22:06:50 +08:00
2,没 break 吧
amiwrong123
2019-08-17 22:14:59 +08:00
@v2overflow
你说 switch case 啊,因为每个分支都有 return,所以不用加 break,加在后面也执行不到。
ywcjxf1515
2019-08-17 22:18:10 +08:00
mFactory.Manufacture("XXX")的结果是,父类引用指向子类对象,后面 show 调用的是父类的方法,方法内容由子类定,父类的 show 方法是默认的包可见性,就不能 access 父亲的 show 方法。你可以向下转型,子类引用指向子类对象,这样 show 方法是子类的 show 方法,可见性是 public。
iEverX
2019-08-17 22:20:00 +08:00
1. 因为确实没用到。Java 从来不要求使用了方法就需要 import
2. 应该没问题,ide 反应慢吧
amiwrong123
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
2019-08-17 22:34:11 +08:00
@iEverX
1.你说的这点,勉强我可以接受,但我还没在书中找到证实。。
2.应该不是 idea 反应慢吧,不然它这反射弧也太长了吧。。。
iEverX
2019-08-17 22:45:24 +08:00
ywcjxf1515
2019-08-17 22:55:23 +08:00
@amiwrong123 疑问 1 里你补加的 public 是在类上的吧,没加之前是默认的包可见性,方法也跟着是。
因为你调用这个 show 方法时,没有出现父类,就不用导入。你可以写一个工厂类,工类类方法返回一个 ArrayList,调用这个工厂类方法,同样不用引用变量接着,直接调用 ArrayList 的方法,你会发现同样不用导入 ArrayList。
amiwrong123
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
2019-08-17 23:12:04 +08:00
@ywcjxf1515
关于访问权限我懂了,先是看类的访问权限,再是看类里各个方法的访问权限。两个都可以才可以访问到。
关于直接调用 show,直接原因应该就是因为我没有用引用去接产品类对象,所以可以直接调用。但总感觉没理解到位==
amiwrong123
2019-08-17 23:16:59 +08:00
@iEverX
疑问 2 解决,就是因为 default 返回 null 的原因。真的反应慢。
iEverX
2019-08-17 23:30:21 +08:00
import other.Product 只是把名字 Product 当作 other.Product。既然没有用 Product 这个名字,当然就不用 import

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/592767

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX