抽象工厂学习
作者:caoglish
链接:https://www.zhihu.com/question/20367734/answer/82361745
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
链接:https://www.zhihu.com/question/20367734/answer/82361745
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
今天正好在学习抽象工厂和工厂方式,我就把我的理解写一写。
工厂一般理解就是减少new创建对象的方式,用接口的方式来返回一个对象,而new创建的方式被封装了。然而,这个是初级认识,这不足以理解到工厂方式的真正目的。
所以我要用我的方式帮助大家理解。
第一部分: 抽象工厂
一般来说,抽象工厂最简单形态也至少有4个元素:
我先用一个例子来实体说明抽象工厂是什么
我现在有三个神枪手,他们聚在一起讨论他们玩枪的经历,
所以,当产品非常多的时候,产品之间关系又非常复杂,但却又可以进行抽象的时候,就是使用抽象工厂模式最好的时候了。
工厂方法目的是生产产品,所以能看到产品,而且还要使用产品。当然,如果产品在创建者内部使用,那么工厂方法就是为了完善创建者,从而可以使用创建者。另外创建者本身是不能更换所生产产品的。
工厂方法生产产品,可以给系统用,可以给客户端用,也可以自己这个类使用。自己这个类除了这个工厂方法外,还能有其他功能性的方法
其实仔细想想,这个两个模式是有交集的,在极端的情况下,这两个模式其实是一样的。所以可以这样理解
工厂一般理解就是减少new创建对象的方式,用接口的方式来返回一个对象,而new创建的方式被封装了。然而,这个是初级认识,这不足以理解到工厂方式的真正目的。
所以我要用我的方式帮助大家理解。
第一部分: 抽象工厂
一般来说,抽象工厂最简单形态也至少有4个元素:
- 客户端(client)
- 工厂(factory)
- 产品A(product A)
- 产品B(product B)
我先用一个例子来实体说明抽象工厂是什么
我现在有三个神枪手,他们聚在一起讨论他们玩枪的经历,
- 神枪手1:AK47打枪最好,杀伤力大。
- 神枪手2:沙漠之鹰最好,准。
- 神枪手3:连弩才好,上古兵器。
他们争论相持不下,所以决定比试一下,然后约定一个月后来鄙视。然后我们看到三个人分别去各自的工厂去购买武器。
神射手1 去了AK47工厂,购买他们生产的武器和子弹
神射手2 去了沙漠之鹰工厂,购买他们生产的武器和子弹
神射手3,去了连弩工厂,购买他们生产的武器和“子弹”
一个月后,我们看到了3个人分别拿出来以下的武器组合
这三个人虽然用的武器不一样,但是每件武器都要做两件事
最后,他们通过比赛谁,看哪种武器是最优秀的。
我们回头去看看,发现虽然三个人去了不同的工厂,用了不同的武器,用了不同的子弹,但是他们的相似之处太多,可以抽象出来。抽象出来的关系框架就是抽象工厂模式
- 武器工厂生产武器
- 武器工厂生产武器所用的子弹
- 武器可以装载子弹
- 武器可以射击子弹
- 神射手装载子弹
- 神射手射击子弹
那么把关系画出来就是:
然后抽象一下成工厂模式就是:
图画出来了,然后我们要如何理解抽象工厂模式. 过去人们都是从工厂开始解释,其实我个人觉得,倒过来讲反而更好理解。而理解抽象工厂模式的关键在于如何理解“产品之间特定关系”。
- 用户要调用产品之间的这个特定关系
- 这个特定关系只有产品A和产品B之间才有,所以我们需要产品A和产品B
- 要获得产品A和产品B,我们要去生产这个产品A和产品B的那个工厂,叫工厂生产这个产品A和产品B
那么用例子来说,就是:
- 神枪手喜欢装载子弹和射击的感觉(他们就是喜欢这个,只要有武器符合这个条件就行)
- 那么他们就是需要武器(枪或者连弩)和子弹,这个武器是可以装载相应子弹和射击相应子弹的
- 他们可以去特定工厂(ak47工厂或者连弩工厂)要求购买武器和相应子弹、
所以理顺抽象工厂的特点是什么?就是如下几个特点:
- 工厂是独立的(独立的类)
- 工厂是生产一整套有产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的
- 工厂是可以抽象的,工厂生产是可以抽象的,就是可以建模,用类来模拟
- 产品是可以抽象的,产品关系是可以抽象的
- 客户端是用来调用并理顺这些产品之间的关系(或指定工作流程)
- 不同工厂生产出的产品实例之间是不接触的,这个是靠客户端来封装实现的。
一个射击学员刚入门,听到射击老师说射击的几个要素: 武器,子弹,武器装载子弹,武器打出子弹。这个学员跃跃欲试,就跑到Ak47工厂买了枪,然后跑到沙漠之鹰工厂买了子弹,AK47装载沙鹰子弹,然后打出。学员卒。这就是客户端加载工厂实例后,保证只使用这个工厂的生产的产品和产品之间的关系,确保不和其他工厂的产品实例进行接触。
老师听说后,为了避免这个悲剧发生,承包了武器和子弹购买,要用AK47就必须在AK47工厂购买AK47和AK47子弹,保证了AK47加载沙漠之鹰子弹这样的悲剧发生了。
最终当我们调用客户端的行为时候,只要让客户端“加载”实例化的特定工厂,返回结果就是这个“特定工厂”所加工出来的“特定产品”的“特定关系”方法的结果了。
所以,当产品非常多的时候,产品之间关系又非常复杂,但却又可以进行抽象的时候,就是使用抽象工厂模式最好的时候了。
以上就是抽象工厂模式的个人理解
--------
第二部分: 工厂方法
工厂方法就两个元素:
- creator(创建者)
- product(产品)
而工厂方法就是一个创建者这个类的一个方法而已,这个方法就是用来封装产品的创建。
第三部分: 抽象工厂 和工厂方法的不同点
我从一下几个方面来理解抽象工厂和工厂方法不同点
- 抽象工程关键在于产品之间的抽象关系,所以至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。
- 抽象工厂中客户端把产品的抽象关系理清楚,在最终使用的时候,一般使用客户端(和其接口),产品之间的关系是被封装固定的;而工厂方法是在最终使用的时候,使用产品本身(和其接口)。
工厂方法目的是生产产品,所以能看到产品,而且还要使用产品。当然,如果产品在创建者内部使用,那么工厂方法就是为了完善创建者,从而可以使用创建者。另外创建者本身是不能更换所生产产品的。
- 抽象工厂的工厂是类;工厂方法的工厂是方法。
工厂方法生产产品,可以给系统用,可以给客户端用,也可以自己这个类使用。自己这个类除了这个工厂方法外,还能有其他功能性的方法
其实仔细想想,这个两个模式是有交集的,在极端的情况下,这两个模式其实是一样的。所以可以这样理解
- 给工厂方法模式加一个客户端,除了客户端都不用这个创建者。这个时候创建者就是工厂类了。(单一产品的特定关系这个时候就是没有关系)
- 抽象工厂模式中,在客户端内部编程时候,就可以把工厂类当作创建者。
天空曾经飘过一片云,不留下一丝痕迹