设计模式学习之如何建造一个简单工厂(工厂模式一)

定义:

工厂模式又可以分为了工厂方法模式、简单工厂模式、抽象工厂模式,最常用的是简单工厂模式和工厂方法模式,下面就开始介绍工厂方法模式和简单工厂模式。

工厂方法模式是经常使用的一种设模式,基本可以分为产品,工厂和使用者。定义一个用于创建对象的接口,它的子类决定实现实例化哪一个类。最基本的工厂方法模式:包括一个抽象工厂类,定义工厂;工厂类实现工厂生产的具体细节;产品的抽象类,定义产品的属性和行为,实际的产品类,最终生产的产品。

举例:

举个例子,现在某地方需要新建一个工厂用来生产汽车,汽车的产品不限,包括:奔驰、路虎等等。首先新建的工厂前,首先拟定工厂的方案,一个抽象类AbstrcatCarFactory ;开始新建工厂CarFactory ;工厂建好了,需要设计产品Car ;更加不同的产品,细化产品细节LandOver 、Benz ;万事具备后只剩生产,建一个Woker 类。最终一辆辆成品汽车送去汽车试验场开始试验检测性能等品质。


/**
 * 汽车工厂的抽象类
 */
public abstract class AbstrcatCarFactory {

    public abstract <T extends Car>  T createCar(Class<T> c);
}

/**
 *汽车工产
 */
public class CarFactory  extends  AbstrcatCarFactory{
    //生产汽车
    @Override
    public <T extends Car> T createCar(Class<T> c) {
        Car car = null;
            try {
                car =(T)Class.forName(c.getName()).newInstance();
            } catch (IllegalAccessException e) {
                
            } catch (ClassNotFoundException e) {
               
            } catch (InstantiationException e) {
                
            }

            return (T) car;
    }
}

/**
 * 汽车接口
 */
public interface Car {

    void travel();
}
/**
 * 奔驰
 */
public class Benz implements Car{
    @Override
    public void travel() {
        System.out.println("奔驰可以去验车了");
    }
}
/**
 * 路虎
 */
public class LandOver implements Car{

    @Override
    public void travel() {
        System.out.println("路虎可以去验车了");
    }
}

public class Woker {
    public static void main(String[] args) {
        //汽车工厂
        AbstrcatCarFactory carFactory = new CarFactory();
        //生产奔驰车
        Benz benz = carFactory.createCar(Benz.class);
        benz.travel();
        //生产路虎
        LandOver landOver = carFactory.createCar(LandOver.class);
        landOver.travel();
    }
}

执行结果:
奔驰可以去验车了
路虎可以去验车了

优势:

从上面的示例代码中,可以看出工厂方法模式,具有良好的封装性;产品通过工厂来生产,产品的实例化都工厂类负责,调用者无序考虑其他因素,降低了产品和工人两个模块间的耦合度,而且屏蔽了产品的细节;同时,工厂类通过泛型限制了产品类型,只能是汽车;易于扩展,如果新增了一个产品类型,只需要实现了产品的抽象接口,如果工厂不满足产品的生产需求,需要对工厂进行改造,这些对于调用者来说是影响很低。

 工厂方法模式,符合迪米特法则,调用者只需要知道产品的抽象类,不需了解具体的实现类;同时也符合依赖倒置原则,工厂定义方法参数产品的抽象类;同时也符合里氏替换原则,定义的是抽象类,实际传入的实现类。

工厂模式的引申:

一、简单工厂模式

工厂方法模式只是提供了一个规范,通过不同的场景,可以延申的范围更广,比如在实际项目中,并不需要新建工厂,只需要使工厂的静态方法,这种引申称之为简单工厂模式,只需要将上述的代码简单修改,去掉抽象工厂类,将工厂类生产产品的方法修改为静态方法:

/**
 * 汽车工厂
 */
public class CarFactory{
    //生产汽车
    public  static  <T extends Car> T createCar(Class<T> c) {
        Car car = null;
            try {
                car =(T)Class.forName(c.getName()).newInstance();
            } catch (IllegalAccessException e) {

            } catch (ClassNotFoundException e) {

            } catch (InstantiationException e) {

            }
            return (T) car;
    }
}

public class Woker {
    public static void main(String[] args) {
        //生产奔驰车
        Benz benz = CarFactory.createCar(Benz.class);
        benz.travel();
        //生产路虎
        LandOver landOver = CarFactory.createCar(LandOver.class);
        landOver.travel();
    }
}

如此修改代码变得更加简洁,所以称之为简单工厂模式,也被称为静态工厂模式,不过调整后的代码扩展性下降,不符合开闭原则,但是并没有影响者其使用。 

二、多工厂模式

        实际项目中,一个工产可能并不满足需求,还可以根据产品的不同,可能不同的产品初始化的参数不同。这时候就可以根据不同的产品新建不同的工厂。这样一来的话也同样存在不容易扩展的问题,每新增一个产品就要新增一个工厂。当然还是根据场景需求来适度使用。在复杂的应用中采用多工厂的方法,增加一个协调类,避免调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口。

三、替代单例模式

        单例模式生成的对象是固定的,如果一个项目中需要生成多个不同的单例,那岂不是要实现多个单例。那如果用工厂方法模式就解决现在的问题。通过静态代码块来加载生成单例,通过返回和类构造器生成单例对象,提供一个静态方法getSingleten()获取单例对象。

/**
 * 单例工厂
 */
public class SingleFactory {

    //单例对象
    private static  Singleton singleton;

    static {
        try {
            Class<?> c = Class.forName(Singleton.class.getName());
            //获取无参构造
            Constructor<?> constructor = c.getDeclaredConstructor();
            //设置无参构造是可以访问的
            constructor.setAccessible(true);
            //产生一个示例对象
            singleton = (Singleton) constructor.newInstance();

        } catch (InstantiationException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        } catch (NoSuchMethodException e) {

        } catch (ClassNotFoundException e) {

        }
    }
    //获取单例
    public static  Singleton getSingleten(){
        return  singleton;
    }
}

四、延迟初始化 

对象在被使用后,并不想他立即释放,保证其初始化状态,等待下次使用。可以新建一个容器Map用来存放对象,key是对象的类型,value为实例对象。首先先判断实现对象是否在容器中,如果存在则直接返回, 不存在则重新实例化对象。


/**
 * 延迟初始化
 */
public class ProductFactory {
    //实例容器
    private  static  final Map<String,Product> map = new HashMap<>();
    public static  synchronized  Product createProduct(String type){
        Product product = null;
        if(map.containsKey(type)){
             product = map.get(type);
        }else{
            if(type.equals("Product1")){
                product = new ConcreteProduct1();
            }else {
                product = new ConcreteProduct2();
            }
        }
        
        return  product;
    }

}

总结: 

工厂方法模式,具有封装性好,易扩展,松耦合的特点。在实际项目中,还可以通过配置文件的形式来设定产品类和工厂类型。这样操作就具有灵活性。

参考《设计模式之禅》秦小波著

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值