设计模式----简单工厂&工厂方法模式&抽象工厂模式

我觉得学设计模式,首先明白是什么?最终目标是学会怎么用到实际项目中。

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就是工厂,对应于抽象工厂;
每个工厂生产的鼠标和键盘就是产品,对应于工厂方法;

用了工厂方法模式,你替换生成键盘的工厂方法,就可以把键盘从罗技换到微软。但是用了抽象工厂模式,你只要换家工厂,就可以同时替换鼠标和键盘一套。如果你要的产品有几十个,当然用抽象工厂模式一次替换全部最方便(这个工厂会替你用相应的工厂方法)

所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值