(Java - SE)设计模式之工厂方法
从今天开始每天一篇关于记录23种设计模式中的设计思想!
今天来说的是工厂方法:
简而言之就是对于同一个目的你有不同的实现,但是恰好我们又不知道该使用哪一个实现面对这种情况我们就可以考虑使用工厂方法的设计思想。
其实书本上的例子看看即可,切不可去硬记它还是那句话这是一种思想模式化是具有灵魂的!
工厂方法的设计灵魂就在于像上面提到过的(某一模块的一个目的的多种行为实现我都提供好了,但是具体按照你自己的需求去选择用哪个就是你的事儿了)
来我们一起来看看Java中的工厂方法是怎么实现的?先贴出来我从书上看到的,然后谈谈利弊再贴出经过我改造的!
书上的工厂方法思想:
(书) - StorageInfo接口[用来强调目标功能]
public interface StorageInfo {
// 定义存储功能
public abstract void storage();
}
(书) - StorageInfo接口的实现类HardDiskImpl[作用提供具体的实现策略]
public class HardDiskImpl implements StorageInfo {
@Override
public void storage() {
// 使用硬盘存储
System.out.println("使用硬盘存储信息 ...");
}
}
(书) - StorageInfo接口的实现类FloppyDiskImpl[作用提供具体的实现策略]
public class FloppyDiskImpl implements StorageInfo {
@Override
public void storage() {
// 使用软盘存储
System.out.println("使用软盘存储数据 ...");
}
}
(书) - StorageFactory接口[工厂接口准备被指定命令的时候返回对应的实例]
public interface StorageFactory {
// 返回构建 StorageInfo 接口实现类的实例
public abstract StorageInfo builder();
}
(书) - StorageFactory接口的实现类[返回Xxx类的实例]
public class HardDiskFactory implements StorageFactory {
@Override
public StorageInfo builder() {
return new HardDiskImpl();
}
}
(书) - StorageFactory接口的实现类[返回Xxx类的实例]
public class FloppyDiskFactory implements StorageFactory {
@Override
public StorageInfo builder() {
return new FloppyDiskImpl();
}
}
(书) - 测试
@Test
public void testBookCode() {
StorageFactory sf = new HardDiskFactory();
sf.builder().storage();// 打印 使用硬盘存储信息 ...
sf = new FloppyDiskFactory();
sf.builder().storage();// 打印 使用软盘存储数据 ...
}
如此便实现了工厂的思想,书上是借助这种方式实现的,那么看到这里很多人就有问题了。典型问题如下:
-1).为什么要搞这些花花肠子?直接new不好吗?
回答:不好,因为直接new虽然可以但是你想想,我们要做的事情测初衷就是有一致目的的两种实现策略,说明二者功能上是一样的这就是我们为什么要用接口将其功能抽取的原因也是为什么将其聚合的原因,倘若行为 不相干的两个类我们通过接口来约束它们有何意义呢?
接着向下刨
我们的最终目的是要那两个行为策略所在实现类的实例,而要想获取他们的实例其接收类型必须是他们实现的接口StorageInfo,这也就是为什么我们在定义工厂接口方法中返回值类型是StorageInfo接口的原因了。
-2).按照这种做法那岂不是需要很多的工厂的实现类来返回实例吗?
对,按照书上的做法是这样的。这应该也算是一个弊端的,但是我们稍加修改就可以干掉这个弊端,如果要写太多的工厂的实现类真实让人头疼,不利于扩展!
改进:
其它代码不变,写一个通用的工厂接口的实现类
(己)StorageFactoryImpl
public class StorageFactoryImpl<E extends StorageInfo> implements StorageFactory {
private Class<?> clazz;
// 无参构造器
public StorageFactoryImpl(Class<?> clazz) {
this.clazz = clazz;
}
@SuppressWarnings("unchecked")
@Override
public StorageInfo builder() {
Object instance = null;
try {
// 通过反射创建指定类型的实例
instance = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
// 转型
return (E) instance;
}
}
这样的话我们仅仅需要一个工厂接口的实现类就可以完成原来的工作。
(己)测试
@Test
public void testBookCode() {
StorageFactory sf = new StorageFactoryImpl<HardDiskImpl>(HardDiskImpl.class);
sf.builder().storage();// 打印 使用硬盘存储信息 ...
}
上面就是今天探讨的设计模式中的工厂方法,如有不对之处还请不吝赐教!