java设计模式之——简单工厂、工厂方法模式、抽象工厂模式(创建性)
1、简单工厂模式
应用场景,程序设计中通过工厂方法接受一个参数,创建不同类类型的实例。
设计示意图
实例
1、定义抽象产品类
public abstract class Rice {
public void prepare(){
System.out.println("准备米饭!");
}
public void cook(){
System.out.println("烹饪米饭!");
}
public void packageRice(){
System.out.println("打包米饭!");
}
}
2、产品类实现类,牛肉饭、羊肉饭
public class BeafRice extends Rice {
@Override
public void prepare(){
System.out.println("准备牛肉饭!");
}
@Override
public void cook(){
System.out.println("烹饪牛肉饭!");
}
@Override
public void packageRice(){
System.out.println("打包牛肉饭!");
}
}
public class SheetRice extends Rice {
@Override
public void prepare(){
System.out.println("准备羊肉饭!");
}
@Override
public void cook(){
System.out.println("烹饪羊肉饭!");
}
@Override
public void packageRice(){
System.out.println("打包羊肉饭!");
}
}
3、简单工厂,根据传入参数生产不同类型产品
public class SimpleRiceFactory {
private SimpleRiceFactory (){};
private static class Innerclass{
public static final SimpleRiceFactory simpleRiceFactory = new SimpleRiceFactory ();
}
public static SimpleRiceFactory getInstance(){
return Innerclass.simpleRiceFactory;
}
public Rice produceRice(Class rice){
Rice riceTemp = null;
try {
riceTemp = (Rice)Class.forName(rice.getName()).newInstance();
} catch (Exception e) {
System.out.println("不支持Rice类接口类型");
e.printStackTrace();
// TODO: handle exception
}
return riceTemp;
}
}
4、产品使用者,服务员,根据客户需求,订购米饭!
public class Waiter {
private SimpleRiceFactory simpleRiceFactory;
public Waiter(SimpleRiceFactory simpleRiceFactory){
this.simpleRiceFactory= simpleRiceFactory;
}
public void order(Class type){
Rice rice = simpleRiceFactory.produceRice(type);
rice.prepare();
rice.cook();
rice.packageRice();
}
}
5、 实现客户端
public class Client {
public static void main(String[] args) {
Waiter waiter = new Waiter(SimpleRiceFactory.getInstance());
waiter.order(BeafRice.class);
waiter.order(SheetRice.class);
}
}
总结
1、当饭的"产品种类"(Rice)频繁变化时,waiter类无需修改。
2、去除了客户端与具体产品的依赖,封装了对象的创建过程。
3、工厂类中包含了所有实例创建的逻辑,一旦工厂出问题,所有客户端都会有问题。
4、当增加产品类型,如面条类,则那么SimpleRiceFactory则无法满足生产要求,这违反了软件设计的开闭原则。
2、工厂方法模式
相对于简单工厂模式,工厂方法模式更多样化。这种模式包含多个工厂,每个工厂对应一类产品,这样减轻了简单工厂的压力。且在新增类型时也遵循了软件设计的开闭原则,不会对其他产品对应的工厂产生影响。
设计示意图
实例
在简单工厂模式的基础上,新增产品类IProductNoodles 以及产品 BeafNoodles、SheetNoodles。
定义工厂类接口
public interface IProductFactory {
public Object produce(Class type);
}
新增面条类工厂
public class SimpleNoodlesFactory implements IProductFactory{
private SimpleNoodlesFactory(){};
private static class InnerClass{
public static final SimpleNoodlesFactory INSTANCE = new SimpleNoodlesFactory();
}
public static SimpleNoodlesFactory getInstance(){
return InnerClass.INSTANCE;
}
@Override
public IProductNoodles produce(Class type) {
// TODO Auto-generated method stub
IProductNoodles noodles = null;
try {
noodles = (IProductNoodles)Class.forName(type.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return noodles;
}
}
定义waiter服务员
public class Waiter {
private static IProductFactory productFactory;
public void setIProductFactory(IProductFactory productFactory){
this.productFactory = productFactory;
}
public void orderRice(Class rice){
IProductRice riceTemp = (IProductRice)productFactory.produce(rice);
riceTemp.prepare();
riceTemp.cook();
riceTemp.packageRice();
}
public void orderNoodles(Class noodles){
IProductNoodles noodlesTemp = (IProductNoodles)productFactory.produce(noodles);
noodlesTemp.prepare();
noodlesTemp.cook();
noodlesTemp.packageNoodles();
}
}
定义client客户端
public class Client {
public static void main(String[] args) {
Waiter waiter = new Waiter();
waiter.setIProductFactory(SimpleRiceFactory.getInstance());
waiter.orderRice(BeafRice.class);
waiter.orderRice(SheetRice.class);
waiter.setIProductFactory(SimpleNoodlesFactory.getInstance());
waiter.orderNoodles(BeafNoodles.class);
waiter.orderNoodles(SheetNoodles.class);
}
}
总结
在可维护和可扩展性上非常差,没有利用多态性,容易造成过多的代码。
3、抽象工厂模式
相对于简单工厂模式和工厂方法模式 ,抽象工厂模式引入了产品族的概念。产品族,可以理解为由不同类型产品组合在一起在同一个工厂中生产的类型。结合反射,将工厂方法模式中米饭工厂和面条工厂合并为一个工厂(包含生产米饭和面条)。
修改工厂类的接口如下:
public interface IProductFactory {
public IProductNoodles produceNoodles(Class type);
public IProductRice produceRice(Class type);
}
工厂类实现类如下:
public class ProductFactory implements IProductFactory{
private ProductFactory(){};
private static class Innerclass{
public static final ProductFactory INSTANCE = new ProductFactory();
}
public static ProductFactory getInstance(){
return Innerclass.INSTANCE;
}
@Override
public IProductNoodles produceNoodles(Class type) {
// TODO Auto-generated method stub
IProductNoodles noodles = null;
try {
noodles = (IProductNoodles)Class.forName(type.getName()).newInstance();
} catch (Exception e) {
// TODO: handle exception
}
return noodles;
}
@Override
public IProductRice produceRice(Class type) {
// TODO Auto-generated method stub
IProductRice rice = null;
try {
rice = (IProductRice)Class.forName(type.getName()).newInstance();
} catch (Exception e) {
// TODO: handle exception
}
return rice;
}
}
waiter类如下:
public class Waiter {
private static IProductFactory productFactory;
public void setIProductFactory(IProductFactory productFactory){
this.productFactory = productFactory;
}
public void orderRice(Class rice){
IProductRice riceTemp = (IProductRice)productFactory.produceRice(rice);
riceTemp.prepare();
riceTemp.cook();
riceTemp.packageRice();
}
public void orderNoodles(Class noodles){
IProductNoodles noodlesTemp = (IProductNoodles)productFactory.produceNoodles(noodles);
noodlesTemp.prepare();
noodlesTemp.cook();
noodlesTemp.packageNoodles();
}
}
最后修改客户端为:
public class Client {
public static void main(String[] args) {
Waiter waiter = new Waiter();
waiter.setIProductFactory(ProductFactory.getInstance());
waiter.orderRice(BeafRice.class);
waiter.orderRice(SheetRice.class);
waiter.orderNoodles(BeafNoodles.class);
waiter.orderNoodles(SheetNoodles.class);
}
}
总结
抽象工厂方法模式的不足在于每次新增产品类时,需要修改抽象类接口、抽象工厂实现类。