工厂方法模式

Posted gxl1995

tags:

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

定义

定义一个用于创建对象的接口,让子类决定实例化哪个类。

使用场景

在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,用new就可以完成创建的对象无需使用工厂模式。

uml图

技术分享图片

角色介绍:

  • 抽象工厂:其为工厂方法模式的核心,它定义了一个工厂类所具备的基本行为;
  • 具体工厂:其实现了具体的业务逻辑;
  • 抽象产品:它定义了所有产品的公共行为;
  • 具体产品:实现抽象产品的某个具体产品的对象。

通用代码

产品

抽象产品

/**
 * 抽象产品类
 */
public abstract class Product {
    /**
     * 产品类的抽象方法,
     * 由具体的产品类去实现
     */
    public abstract void method();
}

具体产品A

/**
 * 具体的产品类A
 */
public class ConcreteProductA extends Product {
    @Override
    public void method() {
        System.out.println("我是具体的产品 A");
    }
}

具体产品B

/**
 * 具体的产品类B
 */
public class ConcreteProductB extends Product {
    @Override
    public void method() {
        System.out.println("我是具体的产品 B");
    }
}

工厂

关于工厂有多种写法,下面就说一下常用的四种写法,用哪一种都行。

第一种

抽象工厂类

public abstract class Factory {
    /**
     * 抽象工厂方法,
     * 又具体的抽象工厂类实现
     */
    public abstract Product createFactory();
}

具体工厂类

public class ConcreteFactory extends Factory {
    @Override
    public Product createFactory() {
//        return new ConcreteProductB();
        return new ConcreteProductA();
    }
}

这种方式比较常见,需要哪个产品,就生产哪个。

第二种

抽象工厂

public abstract class Factory {
    /**
     * 创建产品
     * 具体生产什么由子类去实现
     */
    public abstract <T extends Product> T createProduct(Class<T> clazz);
}

具体工厂

public class ConcreteFactory extends Factory {
    @Override
    public <T extends Product> T createProduct(Class<T> clazz) {
        Product product = null;
        try {
            product = (Product) Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

这种方式时通过反射,需要哪个产品直接传入相应的class就行,非常方便。

第三种

抽象工厂

public abstract class Factory {
    /**
     * 抽象工厂方法,
     * 又具体的抽象工厂类实现
     */
    public abstract Product createFactory();
}

具体工厂A

public class ConcreteFactoryA extends Factory {
    @Override
    public Product createFactory() {
        return new ConcreteProductA();
    }
}

具体工厂B

public class ConcreteFactoryB extends Factory {
    @Override
    public Product createFactory() {
        return new ConcreteProductB();
    }
}

这种创建工厂方式和uml比较契合,每有一个产品创建对应的工厂来生产产品,像这样拥有多个工厂的方法我们称之为多工厂方法模式。

第四种

没有抽象工厂,直接创建工厂如下:

public class Factory {
    public static Product createProduct() {
//        return new ConcreteProductB();
        return new ConcreteProductA();
    }
}

这种方式简化掉了抽象类,将对应的方法改成了静态方法,这种方式称为简单工厂模式或者静态工模式。

实践

我们在项目中经常有保存数据的操作,但是保存的方式有很多种,如Preference,File,数据库等,这些保存方式各有各的优点和缺点,在实际运用中,可能在不同的地方要用不同的方式来存储,但是这些存储都有一个共同的特点就是增,删,改,查。有这四个特性,我们可以考虑运用工厂方法模式来处理这个问题。

先做出对应的uml图来理清结构
技术分享图片

下面就根据这个原理来写代码

IOHandler

public interface IOHandler {
    /**
     * 存储String类型的值
     */
    void putString(String key, String value);

    /**
     * 获取String类型值
     */
    String getString(String key);
}

PreferencesHandler

public class PreferencesHandler implements IOHandler {

    private static volatile PreferencesHandler mInstance;
    private SharedPreferences mSP;

    private PreferencesHandler(Context context) {
        mSP = context.getApplicationContext().getSharedPreferences("cache", Context.MODE_PRIVATE);
    }

    public static PreferencesHandler getInstance(Context context) {
        if (mInstance == null) {
            synchronized (PreferencesHandler.class) {
                if (mInstance == null) {
                    mInstance = new PreferencesHandler(context);
                }
            }
        }
        return mInstance;
    }

    @Override
    public void putString(String key, String value) {
        mSP.edit().putString(key, value).commit();
    }

    @Override
    public String getString(String key) {
        String string = mSP.getString(key, null);
        return string;
    }
}

MemoryHandler

public class MemoryHandler implements IOHandler {
    int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    int cacheSize = maxMemory / 8;

    private static volatile MemoryHandler mInstance;
    private LruCache<String, Object> mLruCache;

    private MemoryHandler() {
        mLruCache = new LruCache<>(cacheSize);
    }

    public static MemoryHandler getInstance() {
        if (mInstance == null) {
            synchronized (MemoryHandler.class) {
                if (mInstance == null) {
                    mInstance = new MemoryHandler();
                }
            }
        }
        return mInstance;
    }

    @Override
    public void putString(String key, String value) {
        mLruCache.put(key, value);
    }

    @Override
    public String getString(String key) {
        return (String) mLruCache.get(key);
    }
}

IOFactory

public class IOFactory {
    /**
     * 获取相应的存储方法
     * @param clazz 具体的IOHandler子类
     */
    public static <T extends IOHandler> T getIOHandler(Class<T> clazz) {
        IOHandler handler = null;
        try {
            handler = (IOHandler) Class.forName(clazz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) handler;
    }
}

上面就是大致的思路,可更加这个思路扩展。


以上是关于工厂方法模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式-简单工厂工厂方法模式抽象工厂模式详解

工厂方法模式

设计模式-工厂方法模式(Go实现)

C++工厂模式(简单工厂工厂方法抽象工厂)

C++工厂模式(简单工厂工厂方法抽象工厂)

设计模式---工厂模式