设计模式之工厂模式
工厂模式:
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式(Factory):
应用场景:又叫做静态工厂方法(StaticFactory Method)模式,但不属于 23 种设计模式之一。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 Bean 对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定
创建一个简单工厂模式的案例:通过简单工厂去生产不同牌子的牛奶,比如蒙牛,特仑苏。首先需要有个牛奶的接口供2种品牌去实现,然后创建2个品牌的牛奶类去实现该接口,最后创建工厂类提供方法去做简单的实现。
创建接口类:
public interface Milk { String getName(); }
创建两个品牌牛奶的实现类:
public class TeLunSuMilk implements Milk { @Override public String getName() { return "特仑苏牛奶"; } } public class MengNiuMilk implements Milk { @Override public String getName() { return "蒙牛牛奶"; } }
创建一个工厂:
public class SimpleFactory { public Milk getMilk(String name){ if("特仑苏".equals(name)){ return new TeLunSuMilk(); }else if("蒙牛".equals(name)){ return new MengNiuMilk(); } return null; } }
测试:
public static void main(String[] args) { SimpleFactory simpleFactory = new SimpleFactory(); //输出 特仑苏牛奶 System.out.println(simpleFactory.getMilk("特仑苏").getName()); }
工厂方法模式(Factory Method):
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
public interface Factory { Milk getMilk(); }
两个工厂实现类:
public class MengNiuFactory implements Factory { @Override public Milk getMilk() { return new MengNiuMilk(); } } public class TeLunSuFactory implements Factory { @Override public Milk getMilk() { return new TeLunSuMilk(); } }
测试:
public static void main(String[] args) { MengNiuFactory mengNiuFactory = new MengNiuFactory(); //输出 蒙牛牛奶 System.out.println(mengNiuFactory.getMilk().getName()); }
抽象工厂模式(Abstract Factory):
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
定义一个抽象工厂类:
public abstract class AbstractFactory { public abstract Milk getMengNiuMilk(); public abstract Milk getTeLunSuMilk(); //还可以定义共同的逻辑代码 }
定义实现:
public class MilkFactory extends AbstractFactory { @Override public Milk getMengNiuMilk() { //工厂方法模式,这里做一个组合 return new MengNiuFactory().getMilk(); } @Override public Milk getTeLunSuMilk() { return new TeLunSuFactory().getMilk(); } }
测试:这样子即使增加了一个品种,而对于用户而言只是增加了一个 API而已,这里很体现开闭原则,对拓展开放,对修改关闭。
public static void main(String[] args) { MilkFactory milkFactory = new MilkFactory(); //输出 特仑苏牛奶 // 简单明了,简化用户配置,直接选择 //保证代码健壮性 易于拓展 System.out.println(milkFactory.getTeLunSuMilk().getName()); }
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例,也就是创建的是一个产品线下的多个产品。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。工厂方法创建 "一种" 产品,他的着重点在于"怎么创建",也就是说如果你开发,你的大量代码很可能围绕着这种产品的构造,初始化这些细节上面。也因为如此,类似的产品之间有很多可以复用的特征,所以会和模版方法相随。 只对结果负责,不要三无产品。