• 【设计模式实战】简单工厂、工厂方法、抽象工厂:原理篇


    小明开发的应用,经常要从XML或者Asset中读取省市区数据。

    小明是这样写的:

    public abstract class IOHandler {
        /**
         * 添加
         */
        public abstract void add(String id, String name);
    
        /**
         * 删除
         */
        public abstract void remove(String id);
    
        /**
         * 修改
         */
        public abstract void update(String id, String name);
    
        /**
         * 查询
         */
        public abstract String query(String id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    public class XMLHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String key) {
            return "xml";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    public class AssetHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String name) {
            return "asset";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
        public void test() {
            IOHandler asset = new AssetHandler();
            String result = asset.query("city.txt");
            System.out.println("result:" + result);
    
            IOHandler xml = new XMLHandler();
            result = xml.query("city");
            System.out.println("result:" + result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出结果

    result:asset
    result:xml
    
    • 1
    • 2

    小明的领导一看,说这样写不行,如果AssetHandler换一种实现方式,岂不是每个引用的地方都要改变?假如以后不想通过这些方式读取城市数据,要增加一个读取本地文件的方式,改动起来很不方便。

    领导说生成这种具有相同功能的对象,可以使用工厂模式

    使用工厂模式改造

    小明觉定用简单工厂尝试改造,增加一个工厂来负责生成对象

    public class SimpleFactory {
    
        public IOHandler getHandler(String type) {
    
            IOHandler ioHandler = null;
            switch (type) {
                case "xml":
                    ioHandler = new XMLHandler();
                    break;
                case "asset":
                    ioHandler = new AssetHandler();
                    break;
                default:
                    break;
            }
            return ioHandler;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
        public void test() {
            SimpleFactory factory = new SimpleFactory();
    
            IOHandler asset = factory.getHandler("asset");
            String result = asset.query("city.txt");
            System.out.println("result:" + result);
    
            IOHandler xml = factory.getHandler("xml");
            result = xml.query("city");
            System.out.println("result:" + result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    小明的领导一看,如果要增加新的对象,或者增加一些业务逻辑,岂不是要修改工厂,工厂因此变得复杂和臃肿。

    小明决定使用工厂方法改造:

    public class AssetFactory implements IFactory {
       @Override
       public IOHandler getHandler() {
          return new AssetHandler();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class XMLFactory implements IFactory {
       @Override
       public IOHandler getHandler() {
          return new XMLHandler();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
        public void test() {
            IFactory assetFactory = new AssetFactory();
            IFactory xmlFactory = new XMLFactory();
    
            IOHandler asset = assetFactory.getHandler();
            String result = asset.query("city.txt");
            System.out.println("result:" + result);
    
            IOHandler xml = xmlFactory.getHandler();
            result = xml.query("city");
            System.out.println("result:" + result);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    和简单工厂不同的是,工厂方法是多工厂,每个工厂负责生成一个对象。如果要增加新的对象,只需要增加一个工厂即可,具有良好的扩展性。

    工厂方法模式是简单工厂演化而来的高级版,后者才是真正的设计模式。

    假如情景更复杂呢?
    比如说之前的工厂都是小明写的,但不好用,新来的程序员小张想用自己写的呢?
    我有那么多工厂,我想要一个超级工厂,去管理这些工厂呢?

    这时候就可以用抽象工厂了:

    小明写的Handler:

    public class XiaomingAssetHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String name) {
            return "xiaoming asset";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    public class XiaomingXMLHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String key) {
            return "xiaoming xml";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    小张写的Handler

    public class XiaozhangAssetHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String name) {
            return "xiaozhang asset";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    public class XiaozhangXMLHandler extends IOHandler {
    
        @Override
        public void add(String id, String name) {
            //业务处理
        }
    
        @Override
        public void remove(String id) {
            //业务处理
        }
    
        @Override
        public void update(String id, String name) {
            //业务处理
        }
    
        @Override
        public String query(String key) {
            return "xiaozhang xml";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    创建抽象工厂

    public interface AbstractFactory {
    
        IOHandler getXMLHandler();
    
        IOHandler getAssetHandler();
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建小明的具体工厂

    class XianmingFactory implements AbstractFactory{
    
       @Override
       public IOHandler getXMLHandler() {
          return new XiaomingXMLHandler();
       }
    
       @Override
       public IOHandler getAssetHandler() {
          return new XiaomingAssetHandler();
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建小张的具体工厂

    class XianzhangFactory implements AbstractFactory{
    
       @Override
       public IOHandler getXMLHandler() {
          return new XiaozhangXMLHandler();
       }
    
       @Override
       public IOHandler getAssetHandler() {
          return new XiaozhangAssetHandler();
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建超级工厂

    
    public class FactoryProducer {
    
        public AbstractFactory getFactory(String type) {
    
            AbstractFactory factory = null;
            switch (type) {
                case "xiaoming":
                    factory = new XianmingFactory();
                    break;
                case "xiaozhang":
                    factory = new XianzhangFactory();
                    break;
                default:
                    break;
            }
            return factory;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    开始测试

     public void test() {
            FactoryProducer factoryProducer = new FactoryProducer();
            //创建小明工厂
            AbstractFactory xiaomingFactory = factoryProducer.getFactory("xiaoming");
            //创建小张工厂
            AbstractFactory xiaozhangFactory = factoryProducer.getFactory("xiaozhang");
    
            //使用小明写的Asset读取方式
            IOHandler ioHandler = xiaomingFactory.getAssetHandler();
            String result = ioHandler.query("city.txt");
            System.out.println("result:" + result);
    
            //使用小张写的Asset读取方式
            ioHandler = xiaozhangFactory.getAssetHandler();
            result = ioHandler.query("city.txt");
            System.out.println("result:" + result);
            
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出结果

    result:xiaoming asset
    result:xiaozhang asset
    
    • 1
    • 2

    可以看到,抽象工厂最核心的是,多工厂,多产品的思路。

    比如说富士康在深圳和东莞都有厂,都生产手机和电脑。区别是,深圳生产华为手机和华为电脑,东莞生产苹果手机和苹果电脑。

    又比如说游戏里面,角色类型有人族和兽族,角色等级又有低中高级,人族和兽族就是工厂,各自生产低中高级的角色。

    工厂方法讲解

    看一下工厂方法模式的UML图
    在这里插入图片描述每个工厂,去生成各自的产品

    抽象工厂方法讲解

    看一下工厂方法模式的UML图
    在这里插入图片描述
    有多个工厂,每个工厂生产多个产品

    简单工厂、工厂方法、抽象工厂的对比

    简单工厂:一个工厂方法生产多个产品
    工厂方法:多个具体工厂,一个工厂生产一个产品
    抽象工厂:多个具体工厂,一个工厂生产多个产品

    拿刚刚游戏里面打比方,简单工厂不符合设计模式规范,而使用工厂方法就要写6个工厂之多,这时候使用抽象工厂就非常适合了。

    什么时候用工厂设计模式?

    工厂设计模式的核心是:生产产品

    什么才叫产品?
    比如说自定义的Button,有圆角的,直角的,圆形的
    比如说通知栏样式的适配,根据不同的Android系统版本配置不同的样式
    比如应用的主题,有深色的、浅色的,主题要配置button、textview、dialog等控件
    比如应用的语言,有中文的、英文的

    这些都是产品,它们的本质是一样的,但形态又不同。

    如果仔细观察,应用内很多地方其实是可以用上工厂设计模式的

  • 相关阅读:
    nginx负载均衡+反向代理
    [论文笔记]BiMPM
    前端日期比较大小(超简单版,不需要转换时间戳)
    百度Java面试题前200页都在这里了
    包含min函数栈
    MyBatis缓存机制之一级缓存
    过滤器(Filter)
    uniapp(uncloud) 使用生态开发接口详情4(wangeditor 富文本, 云对象, postman 网络请求)
    Oracle设置日志参数-ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
    nodejs如何实现URL的拆分
  • 原文地址:https://blog.csdn.net/iromkoear/article/details/126410404