设计模式之工厂模式

定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂模式使一个类的实例化延迟到其子类

举个栗子:
定义一个抽象产品类Product负责定义产品的共性,实现对事物的抽象定义;AbstractCreator为抽象工厂,具体如何创建由具体的实现工厂ContractorCreator完成。

//抽象产品类
public abstract class Product {
    //产品类公共方法
    public void method1(){
        //处理业务逻辑
    }
    //抽象方法
    public abstract void method2();
}
//具体产品类A
public class ProductA extends Product {
    @Override
    public void method2() {}
}

//具体产品类B
public class ProductB extends Product {
    @Override
    public void method2() {}
}
// 抽象工厂类
public abstract class AbstractCreator {
    /**
     * 创建一个产品对象,输入参数可以自行设置
     * 同常是String、Enum、Class等,也可为空
     */
    public abstract <T extends  Product> T createProduct(Class<T> c);
}
//具体的实现工厂类
public class ProductCreator extends AbstractCreator {
    @Override
    public <T extends Product> T createProduct(Class<T> c) {
        Product product = null;
        try {
            product = (Product) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        AbstractCreator creator = new ProductCreator();
        creator.createProduct(ProductA.class);

        creator.createProduct(ProductB.class);

        //...业务处理
    }
}

优点
* 结构清晰,易于扩展。在增加产品类的情况下,只需要增加具体的产品类,或者适当的修改具体的工厂类或扩展一个工厂类。
* 屏蔽产品类。产品类如何变化,调用者不需要关心,只需要关心产品的接口。
* 解耦合。高层模块只需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则,也符合依赖倒置原则和里氏替换原则。

扩展

简单工厂模式

去掉抽象工厂AbstractCreator,修改具体的实现工厂ContractorCreator中的方法为static,简化了类的创建过程。也称为静态工厂模式,缺点是工厂类的扩展比较困难

//具体实现工厂类
public class ProductCreator {
    public static <T extends Product> T createProduct(Class<T> c) {
        Product product = null;
        try {
            product = (Product) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        ProductA productA = ProductCreator.createProduct(ProductA.class);
        ProductB productB = ProductCreator.createProduct(ProductB.class);
        productA.method1();
        productB.method1();
    }
}

升级为多个工厂类

当项目比较复杂时,比如一个产品类有许多个具体的产品实现类,每个实现类的初始化方法都不同,可以考虑为每一个产品定义一个创建者,由调用者自己去选择与哪个工厂方法关联。

// 抽象工厂类
//抽象方法之后不再需要参数,因为每个产品工厂只负责创建自己的产品对象
public abstract class AbstractCreator {
    public abstract Product createProduct();

}
//产品子工厂类
public class ProductACreator extends AbstractCreator {
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

替代单例模式

单例工厂可以通过反射创建一个单例类

//单例类
public class Singleton {
    private Singleton(){
    }
    public void doSomething(){
        //相关业务方法
        System.out.println("业务方法被调用");
    }
}
//单例工厂类
public class SingletonFactory {
    private static Singleton singleton;
    static {
        try {
            Class clazz = Class.forName(Singleton.class.getName());
            //获得无参构造
            Constructor constructor = clazz.getDeclaredConstructor();
            //设置无参构造是可访问的
            constructor.setAccessible(true);
            //生成对象
            singleton = (Singleton) constructor.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public static Singleton getSingleton(){
        return singleton;
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        Singleton singleton = SingletonFactory.getSingleton();
        singleton.doSomething();
    }
}

延迟初始化

一个对象被消费完后,并不立即释放,工厂类保持其初始状态,等待再次被使用。

//延迟加载的工厂类
public class ProductFactory {
    //pMap模拟缓存
    private static final Map<String, Product> pMap = new HashMap();
    public static synchronized Product createProduct(String type) throws Exception {
        Product product = null;
        if (pMap.containsKey(type)) {
            product = pMap.get(type);
        } else {
            if ("ProductA".equals(type)) {
                product = new ProductA();
            } else ("ProductB".equals(type)) {
                product = new ProductB();
            }
            //放入缓存
            pMap.put(type, product);
        }
        return product;
    }
}

延迟加载是可以扩展的,比如限制一个产品类的最大实例化数量,可以通过判断map中的已有对象数量实现。例如JDBC中连接数据库最大连接数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值