zoukankan      html  css  js  c++  java
  • Java内功修炼系列一工厂模式

    工厂模式是一种创建型模式,它提供了一种新的创建对象的方式,一般情况下我们都习惯用new关键字直接创建对象。有时候会遇到这种情况,我们需要根据具体的场景选择创建什么类型的对象,可能有多种类型都能选择,但一次只能选一种,针对这种对象可以选择性创建的情况工厂模式就显得十分好用了。工厂模式嘛,顾名思义就是一个很大的工厂,里面有各种我们需要的产品,我们可以根据自己的需求选择买哪种产品,只要告诉工厂我们想要的产品即可。还有一种是抽象工厂模式,这种模式中,我们请求一个具体的产品时,工厂会去找该对象所属类型的工厂要,然后再给我们,从用户角度来看就是一个工厂提供的产品,其实在其内部,产品并不是由它生产,而是由不同类别的具体工厂生产出来由它提供给用户,在这里其实我们所请求的这个工厂它不是一个具体的能生产各类产品的工厂,我们可以称之为抽象工厂,而通过这种工厂生产产品的模式就叫抽象工厂模式。抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。说起来有点绕。等会用具体的实例来说明。

    一、工厂模式实例

    举一个我们上网时经常遇到的例子,假如我们在用QQ音乐听歌,突然听到一首很喜欢的歌想分享一下,在我们选择分享对象的时候会有QQ空间、微信朋友圈以及微博三种选项,但是这时候我们只能选择其中之一进行分享,这就相当于我们需要选择一个对象创建并调用它的分享接口。此时我们可以创建一个工厂,这个工厂负责生产不同的社交圈对象,我们只需要告诉它社交圈的名称,它就能给我们创建对应的对象,而无需我们自己创建。这里的QQ空间、微信朋友圈和微博相当于三种社交类,让它们实现一个社交接口并实现里面的分享方法,这样通过工厂获取到对应的对象之后我们就能分享歌曲到对应的空间了。下面是代码实现过程。

    第一步:创建一个社交软件接口,用来进行音乐分享

    1 /*
    2  * 定义一个社交软件接口
    3  */
    4 public interface ISocialSoftware {
    5     //定义一个分享音乐的接口
    6     public void shareMusic();
    7 }

    第二步:创建三个社交软件类,实现上面的接口

     1 /*
     2  * 定义qq空间类实现社交软件接口
     3  */
     4 public class Qqzone implements ISocialSoftware {
     5 
     6     public void shareMusic() {
     7         System.out.println("分享到qq空间");
     8     }
     9 }
    10 
    11 /*
    12  * 定义微博类,实现社交软件接口
    13  */
    14 public class WeiBo implements ISocialSoftware {
    15 
    16     public void shareMusic() {
    17         System.out.println("分享到微博");
    18     }
    19 
    20 }
    21 
    22 /*
    23  * 定义一个微信类,实现社交软件接口
    24  */
    25 public class WeiXin implements ISocialSoftware {
    26 
    27     public void shareMusic() {
    28         System.out.println("分享到微信朋友圈");
    29     }
    30 }

    第三步:创建工厂类,用来创建不同的社交软件对象

     1 /*
     2  * 创建一个社交软件工厂,提供不同的软件对象
     3  */
     4 public class SocialSoftwareFactory {
     5 
     6     /*
     7      * 获取社交软件对象
     8      */
     9     public static ISocialSoftware getSocialSoftware(String softwareName) {
    10         String name = softwareName;
    11         ISocialSoftware software = null;
    12         switch (name) {
    13         case "qq":
    14             software = new Qqzone();
    15             break;
    16         case "weibo":
    17             software = new WeiBo();
    18             break;
    19         case "weixin":
    20             software = new WeiXin();
    21             break;
    22         default:
    23             System.out.println("找不到该软件");
    24         }
    25 
    26         return software;
    27     }
    28 }

    第四步:模拟用户将qq音乐分享到不同的社交圈

     1 /*
     2  * 用户玩qq音乐分享音乐
     3  */
     4 public class PlayQqMusic {
     5     public static void main(String[] args) {
     6         
     7         // 获取工厂对象
     8         SocialSoftwareFactory factory = new SocialSoftwareFactory();
     9         //用户选择社交软件名称
    10         String softwareName = "weixin";
    11         //根据软件名称分别分享到不同社交软件
    12         ISocialSoftware software = factory.getSocialSoftware(softwareName);
    13         //用户只需修改软件名称,无需关心这个软件是怎么获取到的
    14         software.shareMusic();
    15     }
    16 }

    第五步:分享结果

    1 分享到微信朋友圈

    在上面的例子中,调用工厂的getSocialSoftware(softwareName)方法,会按照指定的软件名称生成一个指向社交软件接口的对象,例如上面的微信,这样我们就能调用微信的音乐分享功能分享qq音乐到朋友圈了。

    二、抽象工厂模式实例

    以在淘宝购物为例,我们可以视淘宝中的服装类为一个大工厂,这个大类中又有女装、女鞋、男装、男鞋等不同的类别,相当于不同类别的服装工厂,而每一个小工厂中又有不同的衣服可以选择,如女装中有卫衣、连衣裙、针织衫三种;女鞋中有帆布鞋、运动鞋、靴子三种;男装中有西服、牛仔裤、运动套装三种;男鞋中有凉鞋、皮鞋、人字拖三种,现在我们通过淘宝服装店买某个衣服的时候,该店不会直接给我们一个具体的衣服,而是通过提供女装、女鞋、男装、男鞋店来让我们选择具体的商品,这里的淘宝服装店相当于一个抽象工厂,能生产女装、女鞋、男装、男鞋等不同的具体工厂,具体的工厂才能提供具体的商品给消费者,下面用代码实现这个例子:

    为了简化,我卖女装和女鞋为例

    第一步:创建女装、女鞋两个接口

     1 /*
     2  * 定义一个女装接口
     3  */
     4 public interface IWomanClothing {
     5     //卖衣服
     6     public void sail();
     7 }
     8 
     9 /*
    10  * 定义一个女鞋接口
    11  */
    12 public interface IWomanShoes {
    13     public void sail();
    14 }

    第二步:定义女装店和女鞋店,分别实现上述接口

    不同女装店

     1 /*
     2  * 定义一个卫衣店,实现女装接口,卖卫衣
     3  */
     4 public class WeiClothingShop implements IWomanClothing {
     5 
     6     @Override
     7     public void sail() {
     8         System.out.println("出售卫衣");
     9     }
    10 
    11 }
    12 
    13 /*
    14  * 定义一个连衣裙店,实现女装接口,出售连衣裙
    15  */
    16 public class DressShop implements IWomanClothing {
    17 
    18     @Override
    19     public void sail() {
    20         System.out.println("出售连衣裙");
    21     }
    22 
    23 }
    24 
    25 
    26 /*
    27  * 定义一个针织衫店,实现女装接口,出售针织衫
    28  */
    29 public class SweaterShop implements IWomanClothing {
    30 
    31     @Override
    32     public void sail() {
    33         System.out.println("出售针织衫");
    34     }
    35 }

    不同女鞋店

     1 /*
     2  * 定义一个帆布鞋店,实现女鞋接口,出售帆布鞋
     3  */
     4 public class ClothShoesShop implements IWomanShoes {
     5 
     6     @Override
     7     public void sail() {
     8         System.out.println("出售帆布鞋");
     9     }
    10 }
    11 
    12 /*
    13  * 创建一个运动鞋商店,实现女鞋接口,出售运动女鞋
    14  */
    15 public class SportsShoesShop implements IWomanShoes {
    16 
    17     @Override
    18     public void sail() {
    19         System.out.println("出售女运动鞋");
    20     }
    21 }
    22 
    23 
    24 /*
    25  * 创建一个女靴店,实现女鞋接口,出售女靴
    26  */
    27 public class BootsShop implements IWomanShoes {
    28 
    29     @Override
    30     public void sail() {
    31         System.out.println("出售女靴");
    32     }
    33 }

    第三步:定义一个抽象工厂类,含有获取女装店和女鞋店的接口

     1 /*
     2  * 创建一个抽象工厂,提供生产女装和女鞋的接口
     3  */
     4 public abstract class AbstractFactory {
     5     // 卖女装
     6     public abstract IWomanClothing sailWomanClothing(String clothing);
     7 
     8     // 卖女鞋
     9     public abstract IWomanShoes sailWomanShoes(String shoes);
    10 }

    第四步:定义一个女装工厂,继承上述抽象工厂,并获取女装实例

     1 /*
     2  * 创建一个女装工厂,生产女装
     3  */
     4 public class WomanClothingFactory extends AbstractFactory {
     5 
     6     @Override
     7     public IWomanClothing sailWomanClothing(String clothing) {
     8         IWomanClothing womanClothing = null;
     9         switch (clothing) {
    10         case "wei":
    11             womanClothing = new WeiClothingShop();
    12             break;
    13         case "dress":
    14             womanClothing = new DressShop();
    15             break;
    16         case "sweater":
    17             womanClothing = new SweaterShop();
    18             break;
    19         default:
    20             break;
    21         }
    22         return womanClothing;
    23     }
    24 
    25     @Override
    26     public IWomanShoes sailWomanShoes(String shoes) {
    27         return null;
    28     }
    29 }

    第五步:定义一个女鞋工厂,生产女鞋

     1 /*
     2  * 创建一个女鞋工厂,生产女鞋
     3  */
     4 public class WomanShoesFactory extends AbstractFactory {
     5 
     6     @Override
     7     public IWomanShoes sailWomanShoes(String shoes) {
     8         IWomanShoes womanShoes = null;
     9         switch (shoes) {
    10         case "cloth":
    11             womanShoes = new ClothShoesShop();
    12             break;
    13         case "sports":
    14             womanShoes = new SportsShoesShop();
    15             break;
    16         case "boots":
    17             womanShoes = new BootsShop();
    18             break;
    19         default:
    20             break;
    21         }
    22         return womanShoes;
    23     }
    24 
    25     @Override
    26     public IWomanClothing sailWomanClothing(String clothing) {
    27         return null;
    28     }
    29 }

    第六步:定义一个类用来生产实际工厂

     1 /**
     2  * 创建一个工厂生产器
     3  */
     4 public class FactoryProducer {
     5     public static AbstractFactory produceFactory(String facName) {
     6         AbstractFactory factory = null;
     7         if (facName.equals("clothing")) {
     8             factory = new WomanClothingFactory();
     9         } else if (facName.equals("shoes")) {
    10             factory = new WomanShoesFactory();
    11         }
    12         return factory;
    13     }
    14 }

    第七步:定义一个消费者购物(重点看注释部分)

     1 /*
     2  * 定义一个消费者购物
     3  */
     4 public class Customer {
     5     public static void main(String[] args) {
     6         // 通过服装店买女装时
     7         // 1、先定义一个女装名称,比如卫衣
     8         String clothingName = "wei";
     9         // 2、服装店先找到女装店:用户买衣服的时候并不知道服装店会通过女装店提供衣服
    10         AbstractFactory clothingFactory = FactoryProducer.produceFactory("clothing");
    11         // 3、然后由女装店把衣服提供给服装店
    12         IWomanClothing clothingShop = clothingFactory.sailWomanClothing(clothingName);
    13         clothingShop.sail();
    14         
    15         // 通过服装店买女鞋时
    16         // 1、先定义一个女鞋名称,比如运动鞋
    17         String shoesName = "sports";
    18         // 2、服装店先找到女鞋店:用户买鞋的时候并不知道服装店会通过女鞋店提供鞋子
    19         AbstractFactory shoesFactory = FactoryProducer.produceFactory("shoes");
    20         // 3、然后由女鞋店提供女鞋给服装店
    21         IWomanShoes shoesShop = shoesFactory.sailWomanShoes(shoesName);
    22         shoesShop.sail();
    23     }
    24 }

    第八步:查看结果

    1 出售卫衣
    2 出售女运动鞋

    从结果可以看出,消费者买卫衣和运动鞋时,其实是它所面向的工厂通过卫衣厂和运动鞋厂提供卫衣和鞋,而不是由它自己生产,所以我们把消费者直接面对的这个工厂可以看成一个抽象工厂,它其实是不存在的。

    以上就是工厂模式及代码实例,实际应用中还要根据具体业务逻辑进行优化。

  • 相关阅读:
    腾讯课堂——基础数据类型(dict字典)
    腾讯课堂——基础数据类型(tuple元祖)
    基础数据类型(list列表)
    第 018讲:函数:灵活即强大(关键字函数,默认函数,收集函数)
    第 015讲:字符串:格式化
    第 013讲: 元组tuple 上了枷锁的列表
    第 012讲:打了激素的数组3
    第 011讲:一个打了激素的数组[02]
    range函数的用法
    第 010讲:一个打了激素的数组[01]
  • 原文地址:https://www.cnblogs.com/hellowhy/p/9647692.html
Copyright © 2011-2022 走看看