zoukankan      html  css  js  c++  java
  • 工厂模式

    工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    工厂模式分为:

    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式

    简单工厂模式:

    首先常见一个Car接口,接口中定义一个run()方法:

    1 package top.bigking.factory.simpleFactory;
    2 
    3 /**
    4  * @Author ABKing
    5  * @Date 2020/2/7 下午3:43
    6  **/
    7 public interface Car {
    8     public void run();
    9 }

    再写两个类实现这个Car接口

     1 package top.bigking.factory.simpleFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/7 下午3:44
     6  **/
     7 public class Benchi implements Car {
     8     @Override
     9     public void run() {
    10         System.out.println("奔驰");
    11     }
    12 }
     1 package top.bigking.factory.simpleFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/7 下午3:44
     6  **/
     7 public class Byd implements Car {
     8     @Override
     9     public void run() {
    10         System.out.println("比亚迪");
    11     }
    12 }

    测试如下:

     1 /**
     2  * @Author ABKing
     3  * @Date 2020/2/7 下午3:45
     4  **/
     5 public class TestSimpleFactory {
     6     @Test
     7     public void testNoFactory(){
     8         Car car1 = new Benchi();
     9         Car car2 = new Byd();
    10         car1.run();
    11         car2.run();
    12 
    13 
    14     }
    15 }

    很明显我们可以看到,作为用户来讲,必须知道接口,还要知道实现类。

    而我们不希望用户知道这么多,我们需要隐藏这些,由此,我们引入了简单工厂模式:

    新建一个工厂类:

     1 package top.bigking.factory.simpleFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/7 下午3:48
     6  **/
     7 public class CarFactory {
     8     public Car getCar(String carName){
     9         if(carName.equals("奔驰")){
    10             return new Benchi();
    11         }
    12         else if(carName.equals("比亚迪")){
    13             return new Byd();
    14         }
    15         return null;
    16     }
    17 }

    进行测试:

     1 package top.bigking.factory.simpleFactory;
     2 
     3 import org.junit.Test;
     4 import sun.security.krb5.internal.ccache.CCacheInputStream;
     5 
     6 /**
     7  * @Author ABKing
     8  * @Date 2020/2/7 下午3:45
     9  **/
    10 public class TestSimpleFactory {
    11     @Test
    12     public void testNoFactory(){
    13         Car car1 = new Benchi();
    14         Car car2 = new Byd();
    15         car1.run();
    16         car2.run();
    17     }
    18     @Test
    19     public void testCarFactory(){
    20         CarFactory carFactory = new CarFactory();
    21         Car car1 = carFactory.getCar("比亚迪");
    22         Car car2 = carFactory.getCar("奔驰");
    23         car1.run();
    24         car2.run();
    25     }
    26 }

    这样用户就不必知道具体的实现了,只需要知道相应的接口即可。

    但是我们应该注意的是:如果我们需要增加新的车,比如兰博基尼,我们就需要添加一个新的类,并且在修改工厂类

    这显然违反了 开闭原则(对扩展开放,对修改关闭)。

    所以我们引入了新的工厂模式:

    工厂方法模式

    把工厂中的方法抽象出来,形成新的类,BenchiFactory和BydFactory

    同时,由于这两个类具有相同的抽象意义,我们定义一个接口,CarFactory

    1 package top.bigking.factory.factoryMethod;
    2 
    3 /**
    4  * @Author ABKing
    5  * @Date 2020/2/10 下午5:28
    6  **/
    7 public interface CarFactory {
    8     public Car getCar();
    9 }
     1 package top.bigking.factory.factoryMethod;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午5:25
     6  **/
     7 public class BenchiFactory implements CarFactory{
     8     @Override
     9     public Car getCar() {
    10         return new Benchi();
    11     }
    12 }
     1 package top.bigking.factory.factoryMethod;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午5:24
     6  **/
     7 public class BydFactory implements CarFactory{
     8     @Override
     9     public Car getCar() {
    10         return new Byd();
    11     }
    12 }

    编写JUnit测试

     1 package top.bigking.factory.factoryMethod;
     2 
     3 import org.junit.Test;
     4 
     5 /**
     6  * @Author ABKing
     7  * @Date 2020/2/10 下午5:27
     8  **/
     9 public class TestFactoryMethod {
    10     @Test
    11     public void testFactoryMethod(){
    12         Car car1 = new BenchiFactory().getCar();
    13         Car car2 = new BydFactory().getCar();
    14         car1.run();
    15         car2.run();
    16     }
    17 }

    工厂方法模式的优点是不需要修改已有的代码,满足开闭原则(对扩展开放,对修改关闭),但是缺点是会增加大量的类,对维护增加了难度。

    另外还有一种工厂模式:抽象工厂模式

    抽象工厂模式是用来增加产品族的,对增加单个产品无能为力

    定义引擎的接口及其实现:

     1 package top.bigking.factory.abstractFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午10:23
     6  **/
     7 public interface Engine {
     8     public void start();
     9     public void run();
    10 }
    11 class GoodEngine implements Engine{
    12 
    13     @Override
    14     public void start() {
    15         System.out.println("好发动机启动!");
    16     }
    17 
    18     @Override
    19     public void run() {
    20         System.out.println("好发动机运行");
    21     }
    22 }
    23 class BadEngine implements Engine{
    24 
    25     @Override
    26     public void start() {
    27         System.out.println("差发动机启动!");
    28     }
    29 
    30     @Override
    31     public void run() {
    32         System.out.println("差发动机运行");
    33     }
    34 }

    定义轮胎的接口及其实现

     1 package top.bigking.factory.abstractFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午10:25
     6  **/
     7 public interface Tyre {
     8     public void roll();
     9 }
    10 class GoodTyre implements Tyre{
    11     @Override
    12     public void roll() {
    13         System.out.println("好轮胎滚动");
    14     }
    15 }
    16 class BadTyre implements Tyre{
    17     @Override
    18     public void roll() {
    19         System.out.println("差轮胎滚动");
    20     }
    21 }

    定义工厂接口

     1 package top.bigking.factory.abstractFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午5:28
     6  **/
     7 public interface CarFactory {
     8     public Engine getEngine();
     9     public Tyre getTyre();
    10 }

    写工厂的两个实现,好车和差车

     1 package top.bigking.factory.abstractFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午10:10
     6  **/
     7 public class GoodCarFactory implements CarFactory {
     8 
     9     @Override
    10     public Engine getEngine() {
    11         return new GoodEngine();
    12     }
    13 
    14     @Override
    15     public Tyre getTyre() {
    16         return new GoodTyre();
    17     }
    18 }
     1 package top.bigking.factory.abstractFactory;
     2 
     3 /**
     4  * @Author ABKing
     5  * @Date 2020/2/10 下午10:32
     6  **/
     7 public class BadCarFactory implements CarFactory {
     8     @Override
     9     public Engine getEngine() {
    10         return new BadEngine();
    11     }
    12 
    13     @Override
    14     public Tyre getTyre() {
    15         return new BadTyre();
    16     }
    17 }

    测试代码:

     1 package top.bigking.factory.abstractFactory;
     2 
     3 import org.junit.Test;
     4 
     5 /**
     6  * @Author ABKing
     7  * @Date 2020/2/10 下午10:34
     8  **/
     9 public class TestAbstractFactory {
    10     //测试好车
    11     @Test
    12     public void testGoodCarFactory(){
    13         CarFactory carFactory = new GoodCarFactory();
    14         Engine engine = carFactory.getEngine();
    15         Tyre tyre = carFactory.getTyre();
    16         engine.start();
    17         engine.run();
    18         tyre.roll();
    19     }
    20     //测试差车
    21     @Test
    22     public void testBadCarFactory(){
    23         CarFactory carFactory = new BadCarFactory();
    24         Engine engine = carFactory.getEngine();
    25         Tyre tyre = carFactory.getTyre();
    26         engine.start();
    27         engine.run();
    28         tyre.roll();
    29     }
    30 
    31 }
    金麟岂是池中物,一遇风云便化龙!
  • 相关阅读:
    华为机试题01背包问题
    丑数
    动态规划(1)
    Linux 后台启动 Redis
    redis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk.
    SQLServer从渣仔到小白
    cmder 增强型命令行工具
    总结在部署分布式爬虫环境过程中常见的若干问题
    【pymongo.errors】Cursor not found
    浅析scrapy与scrapy_redis区别
  • 原文地址:https://www.cnblogs.com/ABKing/p/12273383.html
Copyright © 2011-2022 走看看