我觉得学设计模式,首先明白是什么?最终目标是学会怎么用到实际项目中。
github: https://github.com/zhang-shoukang/design-pattern
简单工厂模式
1. 是什么?
工厂对象决定创建出哪一种产品类的实例,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。
简单的来说,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
2.案例
下面例子中鼠标,键盘,耳麦为产品,惠普,戴尔为工厂。
简单工厂模式不是 23 种里的一种,简而言之,就是有一个专门生产某个产品的类。
比如下图中的鼠标工厂,专业生产鼠标,给参数 0,生产戴尔鼠标,给参数 1,生产惠普鼠标。
3.代码实现:
interface Mouse{}
class HpMouse implements Mouse{}
class DellMouse implements Mouse{}
class MouseFactory {
public Mouse createMouse(String type){
if ("hp".equals(type)){
return new HpMouse();
}else if ("dell".equals(type)){
return new DellMouse();
}
return null;
}
}
public class SimpleFactoryTest01 {
public static void main(String[] args) {
Mouse hpMouse = new MouseFactory().createMouse("hp");
Mouse dellMouse = new MouseFactory().createMouse("dell");
}
}
4.总结
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,
必须对工厂类进行修改,这违背了闭包原则(对扩展开放,对修改关闭),所以,从设计角度考虑,有一定的问题,如何解决?
工厂模式
1.是什么
考虑到简单工厂违背了闭包原则,所以就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
2.案例:
工厂模式也就是鼠标工厂是个父类,有生产鼠标这个接口。
戴尔鼠标工厂,惠普鼠标工厂继承它,可以分别生产戴尔鼠标,惠普鼠标。
生产哪种鼠标不再由参数决定,而是创建鼠标工厂时,由戴尔鼠标工厂创建。
后续直接调用鼠标工厂.生产鼠标()即可
3.代码
interface Provider{
Mouse produce();
}
class HpMouseFactory implements Provider{
public Mouse produce() {
return new HpMouse();
}
}
class DellMouseFactory implements Provider{
public Mouse produce() {
return new DellMouse();
}
}
public class FactoryTest {
public static void main(String[] args) {
HpMouseFactory hpMouseFactory = new HpMouseFactory();
hpMouseFactory.produce();
DellMouseFactory dellMouseFactory = new DellMouseFactory();
dellMouseFactory.produce();
}
}
4.总结
放到最后,做一个和抽象工厂模式的对比,因为很容易混淆两者区别
抽象工厂模式
1.是什么?
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
2.案例:
抽象工厂模式也就是不仅生产鼠标,同时生产键盘。
也就是 PC 厂商是个父类,有生产鼠标,生产键盘两个接口。
戴尔工厂,惠普工厂继承它,可以分别生产戴尔鼠标+戴尔键盘,和惠普鼠标+惠普键盘。
创建工厂时,由戴尔工厂创建。
后续工厂.生产鼠标()则生产戴尔鼠标,工厂.生产键盘()则生产戴尔键盘。
在抽象工厂模式中,假设我们需要增加一个工厂
假设我们增加华硕工厂,则我们需要增加华硕工厂,和戴尔工厂一样,继承 PC 厂商。
之后创建华硕鼠标,继承鼠标类。创建华硕键盘,继承键盘类即可。
在抽象工厂模式中,假设我们需要增加一个产品
假设我们增加耳麦这个产品,则首先我们需要增加耳麦这个父类,再加上戴尔耳麦,惠普耳麦这两个子类。
之后在PC厂商这个父类中,增加生产耳麦的接口。最后在戴尔工厂,惠普工厂这两个类中,分别实现生产戴尔耳麦,惠普耳麦的功能。 以上。
3.代码
interface Mouse{}
class HpMouse implements Mouse{}
class DellMouse implements Mouse{}
interface KeyBo{}
class DellKeyBo implements KeyBo{}
class HpKeyBo implements KeyBo{}
public class AbstractFactoryTest {
public static void main(String[] args) {
PcFactory hpFactory = new HpFactory();
Mouse hpFactoryMouse = hpFactory.createMouse();
KeyBo hpFactoryKeyBo = hpFactory.createKeyBo();
PcFactory dellFactory = new DellFactory();
Mouse dellFactoryMouse = dellFactory.createMouse();
KeyBo dellFactoryKeyBo = dellFactory.createKeyBo();
}
}
abstract class PcFactory {
public abstract KeyBo createKeyBo();
public abstract Mouse createMouse() ;
}
class HpFactory extends PcFactory{
public KeyBo createKeyBo() {
return new HpKeyBo();
}
public Mouse createMouse() {
return new HpMouse();
}
}
class DellFactory extends PcFactory{
public KeyBo createKeyBo() {
return new DellKeyBo();
}
public Mouse createMouse() {
return new DellMouse();
}
}
增加一个工厂
interface Mouse{}
class HpMouse implements Mouse{}
class DellMouse implements Mouse{}
class AsusMouse implements Mouse{}
interface KeyBo{}
class DellKeyBo implements KeyBo{}
class HpKeyBo implements KeyBo{}
class AsusKeyBo implements KeyBo{}
public class AbstractFactoryTest {
public static void main(String[] args) {
PcFactory hpFactory = new HpFactory();
Mouse hpFactoryMouse = hpFactory.createMouse();
KeyBo hpFactoryKeyBo = hpFactory.createKeyBo();
PcFactory dellFactory = new DellFactory();
Mouse dellFactoryMouse = dellFactory.createMouse();
KeyBo dellFactoryKeyBo = dellFactory.createKeyBo();
PcFactory asusFactory = new AsusFactory();
KeyBo keyBo = asusFactory.createKeyBo();
Mouse mouse = asusFactory.createMouse();
}
}
abstract class PcFactory {
public abstract KeyBo createKeyBo();
public abstract Mouse createMouse() ;
}
class AsusFactory extends PcFactory{
@Override
public Mouse createMouse() {
return new AsusMouse();
}
@Override
public KeyBo createKeyBo() {
return new AsusKeyBo();
}
}
class HpFactory extends PcFactory{
public KeyBo createKeyBo() {
return new HpKeyBo();
}
public Mouse createMouse() {
return new HpMouse();
}
}
class DellFactory extends PcFactory{
public KeyBo createKeyBo() {
return new DellKeyBo();
}
public Mouse createMouse() {
return new DellMouse();
}
}
增加一个产品
interface Mic{}
class DellMic implements Mic{}
class HpMic implements Mic{}
class AsusMic implements Mic{}
工厂方法模式和抽象工厂模式对比
工厂方法模式和抽象工厂模式不好分清楚,他们的区别如下:
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。
抽象工厂需要创建一些列产品,着重点在于"创建哪些"产品上,也就是说,如果你开发,你的主要任务是划分不同差异的产品线,并且尽量保持每条产品线接口一致,从而可以从同一个抽象工厂继承。
对于java来说,你能见到的大部分抽象工厂模式都是这样的:
---它的里面是一堆工厂方法,每个工厂方法返回某种类型的对象。
比如说工厂可以生产鼠标和键盘。那么抽象工厂的实现类(它的某个具体子类)的对象都可以生产鼠标和键盘,但可能工厂A生产的是罗技的键盘和鼠标,工厂B是微软的。
这样A和B就是工厂,对应于抽象工厂;
每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;
用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换鼠标和键盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便(这个工厂会替你用相应的工厂方法)
所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线