学习设计模式——工厂方法

这里要先感谢《研磨设计模式》一书的作者,在讲述IoC/DI(控制反转/依赖注入)的时候深入浅出,让我有了清晰的理解,谢谢。
关于IoC/DI
依赖注入:应用程序依赖容器创建并注入它所需要的外部资源
控制反转:容器控制应用程序,有容器反向地向应用程序注入其所需要的外部资源

有效的分离了对象和所需要的外部资源,松耦合,有利于复用


适用于:

  • 让父类在不知道具体实现的情况下,完成自身功能的调用,将具体的实现延迟到子类来实现。
  • 子类通常是做选择来实现产品对象,而非直接实现功能。

优点:

  • 良好的封装性,代码结构清晰——平行化代码结构,有什么样的产品对象就有什么样的产品工厂。或者由带参数的总工厂来生成所有的产品对象。
  • 扩展性非常强——只需要适当的修改具体工厂类或者扩展一个工厂类,就可以实现变化。
  • 可以屏蔽具体的产品类。
  • 典型的解耦模式。

缺点:

  • 具体产品对象和工厂方法的耦合。(关于这点个人认为是理所应当的,不算缺点,毕竟总有类是耦合的,在子类中耦合是解耦父类的一种途径,符合里氏替换原则)

产品类:

public interface Product {
    void doSomething();
}

public class ProductA implements Product {
    //这里私有没有特别的意思,就是不想被外界直接new
    private ProductA(){
    }
    public void doSomething() {
        System.out.println("it's ProductA");
    }
}

public class ProductB implements Product {
    private ProductB(){
    }
    public void doSomething() {
        System.out.println("it's ProductB");
    }
}

工厂类:

public abstract class Factory {
    //这个就是工厂方法,是该模式的核心
    public abstract Product createProduct();

    //这里通过访问工厂的方法来调用具体产品的方法
    //这样产品被封装的很好,而且扩展很强
    public void doSomething() {
        Product p = createProduct();
        if(p!=null){
            p.doSomething();
        }
    }
}

public class FactoryA extends Factory {
    public Product createProduct() {
        try {
            Constructor<?> c = Class.forName(ProductA.class.getName()).getDeclaredConstructor();
            c.setAccessible(true);
            return (Product) c.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

客户端:

public class Client {
    public static void main(String[] args) {
        Factory a = new FactoryA();
        a.doSomething();
    }
}

结果:

it’s ProductA

扩展:
生成单例的工厂类:

public class SingletonFactory {
    private static final Map<String, Object> objectMap = new HashMap<String, Object>();

    public synchronized static <T> T createSingleton(Class<T> c) {
        T t = null;
        String className = c.getName();
        try {
            if (!objectMap.containsKey(className)) {
                Class<?> c1 = Class.forName(className);
                Constructor<?> constructor = c1.getDeclaredConstructor();
                constructor.setAccessible(true);
                t = (T) constructor.newInstance();
                objectMap.put(className, t);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) objectMap.get(className);
    }

    public static void main(String[] args) {
        Product productA1 = SingletonFactory.createSingleton(ProductA.class);
        System.out.println(productA1);
        Product productB1 = SingletonFactory.createSingleton(ProductB.class);
        System.out.println(productB1);

        Product productA2 = SingletonFactory.createSingleton(ProductA.class);
        System.out.println(productA2);
        Product productB2 = SingletonFactory.createSingleton(ProductB.class);
        System.out.println(productB2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值