设计模式之抽象工厂模式

4次阅读

共计 2405 个字符,预计需要花费 7 分钟才能阅读完成。

抽象工厂模式

本来不想写这篇文章的,应该是不想写工厂模式,因为基本大家都会,不过今天看到一个老铁的博客,https://www.yuxuan66.com/16 关于抽象模式的实现,写得不错,看了几遍之后,有了点自己的想法,随便再熟悉一下工厂模式,于是就有了这篇文章,主要是抽象工厂,引用下老铁的例子:咖啡工厂做大做强,引入了新的饮品种类:茶、碳酸饮料。中国工厂仅能制作咖啡和茶,美国工厂仅能制作咖啡和碳酸饮料

使用

我这里创建一个抽象工厂,中国工厂和美国工厂继承它。再创建一个饮料接口,实现各种饮料种类。再创建一个提供者,根据具工厂和种类提供对应的产品

创建一个抽象工厂

/**
 * @program:hope
 * @author:aodeng
 * @微信公众号: 低调小熊猫
 * @create:2018-11-22 14:43
 * 抽象工厂
 **/
public abstract class AbstractDrinksFactory {
    /***
     *
     * @param whatYouLike 你喜欢的饮料类型:coffer,tea,sodas...
     * @return
     */
    public abstract Drink createDrink(String whatYouLike);
}

中国工厂和美国工厂继承它

public class ChinaAbstractDrinksFactory extends AbstractDrinksFactory {
    @Override
    public Drink createDrink(String whatYouLike) {
        Drink drink=null;
        if ("coffer".equals(whatYouLike)){drink=new CofferDrink();
        }else if ("tea".equals(whatYouLike)){drink=new TeaDrink();
        }
        return drink;
    }
}
//
public class USAAbstractDrinksFactory extends AbstractDrinksFactory {
    @Override
    public Drink createDrink(String whatYouLike) {
        Drink drink=null;
        if ("coffer".equals(whatYouLike)){drink=new CofferDrink();
        }else if ("sodas".equals(whatYouLike)){drink=new SodasDrink();
        }
        return drink;
    }
}

再创建一个饮料接口

// 饮料接口
public interface Drink {String getName();
}

实现各种饮料种类

// 咖啡饮料
public class CofferDrink implements Drink {
    @Override
    public String getName() {return "coffer";}
}
// 碳酸饮料
public class SodasDrink implements Drink {
    @Override
    public String getName() {return "sodas";}
}
 // 茶饮料
public class TeaDrink implements Drink {
    @Override
    public String getName() {return "tea";}
}

再创建一个提供者,更具工厂和种类提供对应的产品

 * 工厂提供者
 **/
public class DrinkStore {
    AbstractDrinksFactory abstractDrinksFactory;

    /***
     * 动态的选择工厂
     * @param abstractDrinksFactory
     */
    public DrinkStore(AbstractDrinksFactory abstractDrinksFactory){this.abstractDrinksFactory=abstractDrinksFactory;}

    /***
     * 根据产品类型生产
     * @param whatYouLike
     * @return
     */
    public Drink createDrink(String whatYouLike){return abstractDrinksFactory.createDrink(whatYouLike);
    }
}

Main 方法测试

/**
 * @program:hope
 * @author:aodeng
 * @微信公众号: 低调小熊猫
 * @create:2018-11-22 15:07
 **/
public class Main {public static void main(String[] args) {
        // 使用工厂提供类选择工厂
        DrinkStore store=new DrinkStore(new ChinaAbstractDrinksFactory());
        // 根据产品生产饮料
        Drink drink=store.createDrink("tea");
        // 得到具体工厂的具体饮料
        System.out.println(drink.getName());// 输出 tea
    }
}

简单工厂和抽象工厂有些区别,除了结构上的区别,主要区别在于使用场景不同。

** 简单工厂用于创建单一产品,将所有子类的创建过程集中在一个工厂中,如要修改,只需修改一个工厂即可。简单工厂经常和单例模式一起使用,例如用简单工厂创建缓存对象(文件缓存),某天需要改用 redis 缓存,修改工厂即可。
抽象工厂常用于创建一整个产品族,而不是单一产品。通过选择不同的工厂来达到目的,其优势在于可以通过替换工厂而快速替换整个产品族。例如上面的例子美国工厂生产美国 drink,中国工厂生产中国 drink。
优点
客户端与具体要创建的产品解耦,扩展性和灵活性高 **

** 缺点
增加要创建的对象时,需要增加的代码较多,会使系统变得较为复杂 **

本文由低调小熊猫一文多发操作发布!欢迎关注公众号:低调小熊猫

正文完
 0

设计模式之抽象工厂模式

4次阅读

共计 3315 个字符,预计需要花费 9 分钟才能阅读完成。

0x01. 定义与类型

  • 定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口
  • 无需指定它们具体的类
  • 类型:创建型
  • UML

  • 基本 java 实现
/**
 * 工厂接口
 */
public interface IFactory {AProduct1 createProduct1();
    AProduct2 createProduct2();}

/**
 * 产品 1
 */
public abstract class AProduct1 {public abstract void produce();
}

/**
 * 产品 2
 */
public abstract class AProduct2 {public abstract void produce();
}

/**
 * 工厂实现
 */
public class FactoryImpl implements IFactory {
    @Override
    public ProductImpl1 createProduct1() {return new ProductImpl1();
    }
    @Override
    public ProductImpl2 createProduct2() {return new ProductImpl2();
    }
}

/**
 * 产品 1 实现
 */
public class ProductImpl1 extends AProduct1 {
    @Override
    public void produce() {System.out.println("产品 1");
    }
}

/**
 * 产品 2 实现
 */
public class ProductImpl2 extends AProduct2 {
    @Override
    public void produce() {System.out.println("产品 2");
    }
}

/**
 * 测试与应用
 */
public class Test {public static void main(String[] args) {FactoryImpl factory = new FactoryImpl();
        ProductImpl1 productImpl1 = factory.createProduct1();
        ProductImpl2 productImpl2 = factory.createProduct2();
        productImpl1.produce();
        productImpl2.produce();}
}
  • 输出结果
产品 1
产品 2 
  • 抽象工厂中的元素

    • 工厂接口:在抽象工厂模式中,工厂接口定义了同一类型的工厂可以生产多种不同的产品,定义了产品的种类。当工厂生成的种类发生变化时,要调整接口中的方法,这里违反了开闭原则,但是扩展不同类型的工厂,只需要实现接口就可以了。
    • 工厂实现类:定义了具体的工厂以及具体生成的类型,有多少中类型的工厂,就有多少个具体的实现类。
    • 具体产品的抽象类:一个工厂有可能生产出不同的产品,抽象类定义工厂生产产品的种类,抽象工厂接口中有多少个方法,就有多少个抽象类。
    • 具体产品的实现:最后得到的具体产品,决定了产品在客户端中的具体行为。

0x02. 适用场景

  • 客户端(应用层)不依赖于产品类实例如何被创建,实现等细节
  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现

0x03. 优点

  • 具体产品在应用层代码隔离,无需关心创建细节
  • 将一个系列的产品族统一到一起创建
  • 在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

0x04. 缺点

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
  • 增加了系统的抽象性和理解难度

0x05. 产品等级结构与产品族介绍


  • 以家用电器为例:

    • 美的:空调,热水器,冰箱,洗衣机
    • 海尔:空调,热水器,冰箱,洗衣机
    • 美的的全部产品属于一个产品族
    • 美的的热水器和海尔的热水器属于一个产品等级
    • 美的 海尔 属于不同的工厂
    • 空调,热水器,冰箱,洗衣机 属于同一工厂生产的不同产品

0x06. 样例实现

简介:慕课网的每一门课程都有手记和视频等,课程又分 Java 课程,Python 课程

  • 课程工厂类
// 课程工厂
public interface ICourseFactory {Video getVideo();
    Article getArticle();}
  • 文章 / 视频抽象类
// 文章抽象类
public abstract class Article {public abstract void produce();
}

// 视频抽象类
public abstract class Video {public abstract void produce();
}
  • Java 课程的实现
//Java 课程工厂
public class JavaCourseFactory implements ICourseFactory {
    @Override
    public JavaVideo getVideo() {return new JavaVideo();
    }

    @Override
    public JavaArticle getArticle() {return new JavaArticle();
    }
}

//Java 视频
public class JavaVideo extends Video {

    @Override
    public void produce() {System.out.println("录制 JAVA 课程视频");
    }
}

//Java 文章
public class JavaArticle extends Article {
    @Override
    public void produce() {System.out.println("编写 Java 课程手记");
    }
}
  • Python 课程实现
//Python 课程工厂
public class PythonCourseFactory implements ICourseFactory {
    @Override
    public Video getVideo() {return new PythonVideo();
    }

    @Override
    public Article getArticle() {return new PythonArticle();
    }
}

//Python 视频实现
public class PythonVideo extends Video {
    @Override
    public void produce() {System.out.println("录制 Python 视频");
    }
}

//Python 文章
public class PythonArticle extends Article {
    @Override
    public void produce() {System.out.println("编写 Python 课程手记");
    }
}
  • 测试与应用类
public class Test {public static void main(String[] args) {
        //java 产品族
        ICourseFactory courseFactory = new JavaCourseFactory();
        Video video = courseFactory.getVideo();
        Article article = courseFactory.getArticle();
        video.produce();
        article.produce();}
}
  • 输出结果
录制 JAVA 课程视频
编写 Java 课程手记
  • 样例 UML 类图

0x07. 源码中的抽象工厂

  • java.sql.Connection

    • Statement
    • PreparedStatement
  • java.sql.Statement

    • executorSet
  • MyBatis: SqlSessionFactory

0x08. 源码地址

  • 抽象工厂模式: https://github.com/sigmako/design-pattern/tree/master/abstract-factory

0x09. 参考

  • 慕课网设计模式精讲: https://coding.imooc.com/class/270.html
  • 23 种设计模式(3):抽象工厂模式: https://blog.csdn.net/zhengzhb/article/details/7359385
正文完
 0