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

小明开发的应用,经常要从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图
【设计模式实战】简单工厂、工厂方法、抽象工厂:原理篇_第1张图片每个工厂,去生成各自的产品

抽象工厂方法讲解

看一下工厂方法模式的UML图
【设计模式实战】简单工厂、工厂方法、抽象工厂:原理篇_第2张图片
有多个工厂,每个工厂生产多个产品

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

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

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

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

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

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

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

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

你可能感兴趣的:(Android设计模式,设计模式,java,jvm)