【23种设计模式从零学2—简单工厂与工厂模式】

Hi~又见面啦,从这篇开始我们就要进入正题啦,每篇讲一类设计模式,快来共同进步吧微笑~

一、简单工厂模式:

概念:

 简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

举个列子:

  我是一个吃货,爱吃罐头,需求比较麻烦想吃各种各样的罐头,比如:有时候,我要吃草莓味的罐头,有时,我要桃味的罐头,有时,我又想吃山楂味的罐头;而恰巧古时候的罐头厂长思想比较落后,他们只懂得生产一种味道的罐头,(草莓罐头厂只生产草莓味儿的,桃罐头厂只生产黄桃味儿的,山楂罐头场只生产山楂味的);这样我想吃某一种口味的罐头就得去跑到对应的厂去买。

模式的问题

  你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程呢?

  原始时代:消费者要关心每个类的实现细节。

 角色:产品、消费者

  产品:

/**
 * Created by Sunrui on 2017/5/11.
 * 山楂味罐头实体类
 */
public class CanHawthorn {

    private String taste;

    public CanHawthorn (String taste){
        this.taste = taste;
    }

    public String tell(){
        return this.taste;
    }

}
/**
 * Created by Sunrui on 2017/5/11.
 * 桃味罐头实体类
 */
public class CanPeach {

    private String taste;

    public CanPeach (String taste){
        this.taste = taste;
    }

    public String getTaste(){
        return this.taste;
    }

}
/**
 * Created by Sunrui on 2017/5/11.
 * 草莓罐头实体类
 */
public class CanStrawberry {

    private String taste;

    public CanStrawberry (String taste){
        this.taste = taste;
    }

    public String say(){
        return this.taste;
    }

}
  消费者:

/**
 * Created by Sunrui on 2017/5/11.
 * 消费者
 */
public class ConsumerWithoutFactory {

    public static void main(String[] args){

        CanHawthorn canHawthorn = new CanHawthorn("山楂");
        CanPeach canPeach = new CanPeach("桃");
        CanStrawberry canStrawberry = new CanStrawberry("草莓");

        System.out.println("吃到口味:" + canHawthorn.tell() + "、" +
           canPeach.getTaste() + "、 " + canStrawberry.say());
    }

}

 在还没有工厂的时代:

 我们创建每个对象需要很大的代价,消费者需要直接跟具体的类关联。并且要关心具体类的内部实现细节(这里用通知方法(tell,say,getTaste)代表每个类的内部细节)

-----------------------------------------划时代的分割线-------------------------------------------

  时代在发展,社会在进步,我们进入简单工厂时代~大笑

   简单工厂时代:消费者只需面对工厂,具体实现细节由工厂去跟每个类打交道

  角色:

工厂:为消费者得到产品的媒介

产品父类:抽象类将产品中共有的功能抽象出来,定义共有的产品规范

产品:具体的产品

消费者:略

工厂:

/**
 * Created by sunrui on 2017/5/11.
 */
public class CanFactory {

    public Can createCan(char name){

        switch (name){
            case 'h':
                return new CanHawthorn("山楂");
            case 'p':
                return new CanPeach("桃");
            case 's':
                return new CanStrawberry("草莓");
            default:
                break;
        }

        return null;
    }
}
抽象父类:

/**
 * Created by Sunrui on 2017/5/11.
 * 抽象产品父类
 */
public abstract class Can {

    public Can (){
    }

    /**
     *  定义产品共有的行为
     */
    public abstract String speak();

}

产品:继承父类,按照父类的规范来定义行为

/**
 * Created by Sunrui on 2017/5/11.
 * 山楂味罐头实体类
 */
public class CanHawthorn extends Can{

    private String taste;

    public CanHawthorn (String taste){
        this.taste = taste;
    }

    public String speak(){
       return this.taste;
    }

}
/**
 * Created by Sunrui on 2017/5/11.
 * 桃味罐头实体类
 */
public class CanPeach extends Can{

    private String taste = "桃味";

    public CanPeach (String taste){
        this.taste = taste;
    }

    public String speak(){
        return this.taste;
    }

}

/**
 * Created by Sunrui on 2017/5/11.
 * 草莓罐头实体类
 */
public class CanStrawberry  extends Can{

    private String taste;

    public CanStrawberry (String taste){
        this.taste = taste;
    }

    public String speak(){
        return this.taste;
    }

}

消费者:

/**
 * Created by Sunrui on 2017/5/11.
 * 消费者
 */
public class ConsumerWithSimpleFactory {

    public static void main(String[] args){

        CanFactory canFactory = new CanFactory();
        Can canHawthorn =  canFactory.createCan('h');
        Can canPeach =  canFactory.createCan('p');
        Can canStrawberry=  canFactory.createCan('s');

        System.out.println("吃到口味:" + canHawthorn.speak() + "、" +
                canPeach.speak() + "、 " + canStrawberry.speak());
    }

}

一点理解:

以上是简单工厂模式的几个角色,那么简单工厂模式到底做了那些事情呢?

   1定义抽象产品父类定义,规范了产品共有的属性和方法(细心地你可以发现子类中之前的tellgetTastesay其实都是抽象起来都是相同的方法,定衣父类后统一定义为speak),方便消费者调用

   2、创建了工厂概念屏蔽了具体产品子类的实现细节,架接起消费者与产品之间的沟通桥梁,我们把它理解为一个模子,根据外界给定的原料,在加上自身封装好的判断,生产出不同类型的相应的产品、对象。(网上某篇文章的理解感觉很不错在这引用一下)

   3、对于消费者:只需要创建工厂,与工厂打交道,告诉工厂你需要的产品,让工厂来生产对象,而不需要直接面向你所需要的产品

   但同时简单工厂模式也有一些弊端:假如现在生产线更发达了,多了一中橘子味罐头那我们势必要修改(注意是修改!与接下来的工厂方法模式在这里有实质性的区别)罐头工厂中的createCan()方法,读过前一篇设计模式六大原则的朋友一定会想到,这里就违反了设计模式中的开放封闭原则(实体应该尽量做到可扩展,不可修改),但是相较于没有工厂的模式,简单工厂模式已经迈出了一大步。

为了解决这个弊端,接下来,我们进入到工厂方法模式的学习@A@

-----------------------------------------划时代的分割线-------------------------------------------

二、工厂方法模式:

概念:

  工厂方法模式(FACTORY METHOD)是一种常用的对象创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品。

  与简单工厂模式的差别:

  工厂方法模式比简单工厂模式多了一个概念即抽象工厂

 角色

 抽象工厂:抽象工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。(形似于产品和产品父类的关系)

 具体工厂:为消费者得到产品的媒介,生产产品的具体实体。

 产品父类:抽象类将产品中共有的功能抽象出来,定义共有的产品规范

 产品:具体的产品

 消费者:略


抽象工厂:

/**
 * Created by Sunrui on 2017/5/11.
 * 抽象工厂,用来定义工厂规范
 */
public interface CanFactory {
    Can createCan();
}

具体工厂:

/**
 * Created by Sunrui
 * Create Date: 2017/5/11 
 * Description: 山楂罐头的实体工厂
 */
public class HawthornCanFactory implements CanFactory{

    /**
     * 创建山楂罐头
     * @return CanHawthorn
     */
    public CanHawthorn createCan(){
        return new CanHawthorn("山楂");
    }

}
/**
 * Created by Sunrui
 * Create Date: 2017/5/11
 * Description: 桃罐头的实体工厂
 */
public class PeachCanFactory implements CanFactory{

    /**
     * 创建桃罐头实体
     */
    public CanPeach createCan(){
        return new CanPeach("桃味");
    }

}
/**
 * Created by Sunrui
 * Create Date: 2017/5/11
 * Description: 草莓罐头的实体工厂
 */
public class StrawberryCanFactory implements CanFactory{

    /**
     * 创建草莓罐头实体
     */
    public CanStrawberry createCan(){
        return new CanStrawberry("草莓味");
    }
}

产品父类:

/**
 * Created by Sunrui on 2017/5/11.
 * 抽象产品父类
 */
public abstract class Can {

    public Can (){
    }

    /**
     *  定义产品共有的行为
     */
    public abstract String speak();

}
产品:
/**
 * Created by Sunrui on 2017/5/11.
 * 山楂味罐头实体类
 */
public class CanHawthorn extends Can {

    private String taste;

    public CanHawthorn (String taste){
        this.taste = taste;
    }

    public String speak(){
       return this.taste;
    }

}
/**
 * Created by Sunrui on 2017/5/11.
 * 桃味罐头实体类
 */
public class CanPeach extends Can {

    private String taste = "桃味";

    public CanPeach (String taste){
        this.taste = taste;
    }

    public String speak(){
        return this.taste;
    }

}
/**
 * Created by Sunrui on 2017/5/11.
 * 草莓罐头实体类
 */
public class CanStrawberry  extends Can {

    private String taste;

    public CanStrawberry (String taste){
        this.taste = taste;
    }

    public String speak(){
        return this.taste;
    }

}

消费者:

/**
 * Created by Sunrui on 2017/5/11.
 * 消费者
 */
public class ConsumerWithSimpleFactory {

    public static void main(String[] args){

        //创建的具体的工厂
        CanFactory strawberryCanFactory =  new StrawberryCanFactory();
        CanFactory hawthornCanFactory = new HawthornCanFactory();
        CanFactory peachCanFactory = new PeachCanFactory();

        //创建不通口味的产品
        Can strawberryCan = strawberryCanFactory.createCan();
        Can hawthornCan = hawthornCanFactory.createCan();
        Can peachCan = peachCanFactory.createCan();

        System.out.println("吃到口味:" + strawberryCan.speak() + "、" +
                hawthornCan.speak() + "、 " + peachCan.speak());
    }

}

  怎么样?不知大家会意没?

 接上个简单工厂抛出的问题,如果我们现在多了一个橘子口味的产品,我们只需增加一个抽象工厂类,(注意只是增加,避免对之前的修改),另增加一个橘子味的产品,即可通过新增加的这个抽象工厂得到相应的产品。

 一点理解:

  使用工厂方法后,调用端的耦合度大大降低了。并且对于工厂来说,是可以扩展的(对于这个例子,我们增加了一个口味),无论是灵活性还是稳定性都得到了极大的提高。

 适用场景:

   不管是简单工厂模式,工厂方法模式他们具有类似的特性,所以他们的适用场景也是类似的。

   首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

   其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。

   再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。

 

   好啦,今天的学习就到这里吧,不知各位互联网的小伙伴是否和我一样收货颇丰,相信每天进步一点点,不久之后你就会有质的改变,我们下一篇见!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值