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

Posted mo_weifeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式实战简单工厂工厂方法抽象工厂:原理篇相关的知识,希望对你有一定的参考价值。

小明开发的应用,经常要从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);

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";
    

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";
    

    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);
    

输出结果

result:asset
result:xml

小明的领导一看,说这样写不行,如果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;
    


    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);
    

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

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

public class AssetFactory implements IFactory 
   @Override
   public IOHandler getHandler() 
      return new AssetHandler();
   

public class XMLFactory implements IFactory 
   @Override
   public IOHandler getHandler() 
      return new XMLHandler();
   

    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);
    

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

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

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

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

小明写的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";
    

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";
    

小张写的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";
    

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";
    

创建抽象工厂

public interface AbstractFactory 

    IOHandler getXMLHandler();

    IOHandler getAssetHandler();


创建小明的具体工厂

class XianmingFactory implements AbstractFactory

   @Override
   public IOHandler getXMLHandler() 
      return new XiaomingXMLHandler();
   

   @Override
   public IOHandler getAssetHandler() 
      return new XiaomingAssetHandler();
   


创建小张的具体工厂

class XianzhangFactory implements AbstractFactory

   @Override
   public IOHandler getXMLHandler() 
      return new XiaozhangXMLHandler();
   

   @Override
   public IOHandler getAssetHandler() 
      return new XiaozhangAssetHandler();
   


创建超级工厂


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;
    



开始测试

 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);
        
    

输出结果

result:xiaoming asset
result:xiaozhang asset

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

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

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

工厂方法讲解

看一下工厂方法模式的UML图
每个工厂,去生成各自的产品

抽象工厂方法讲解

看一下工厂方法模式的UML图

有多个工厂,每个工厂生产多个产品

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

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

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

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

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

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

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

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

以上是关于设计模式实战简单工厂工厂方法抽象工厂:原理篇的主要内容,如果未能解决你的问题,请参考以下文章

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

简单工厂模式&工厂方法模式&抽象工厂模式的区别

C#工厂模式的原理

Java进阶篇设计模式之二 ----- 工厂模式

JavaScript设计模式创建型设计模式--简单工厂工厂方法抽象工厂

设计模式抽象工厂模式(Abstract Factory)