工厂模式实现了创建者和调用者的分离。
OOP七大原则和工厂模式相关的:
1、开闭原则:一个软件的实体应当扩展开发,对修改关闭
2、依赖倒转原则:要针对接口编程,不要针对实现编程
3、迪米特法则:只与你直接的朋友通信,避免和陌生人通信
核心本质:
1、实例化对象不使用new,用工厂方法代替
2、选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。
简单工程模式
用来生产同一等级中的任意产品(对于增加的新产品,需要扩展已有代码)
package factory.simple;
//静态工厂类
public class CarFactory {
public static Car getCar(String s){
if(s.equals("wuling")){
return new Wuling();
}else if(s.equals("lsls")){
return new Lsls();
}else
return null;
}
}
其中,Wuling和 Lsls都继承自 Car。
package factory.simple;
public interface Car {
void name();
}
package factory.simple;
public class Wuling implements Car{
@Override
public void name() {
System.out.println("五菱宏光");
}
}
package factory.simple;
public class Lsls implements Car{
@Override
public void name() {
System.out.println("劳斯莱斯");
}
}
缺点就是增加一个新的产品,如果不修改代码,做不到!
简单地说,简单工厂模式通常就是这样,一个工厂类 XxxFactory,里面有一个静态方法,根据我们不同的参数,返回不同的派生自同一个父类(或实现同一接口)的实例对象。
我们强调职责单一原则,一个类只提供一种功能,CarFactory 的功能就是只要负责生产各种 Car。
工厂方法模式
用来生产同一等级结构中的固定产品(支持增加任意产品)。工厂方法,拥有一个顶级工厂接口,每个具体工厂管理自己的产品,通过顶级工厂借口向外界提供工厂的实例。工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。
package factory.method;
public interface Car {
void name();
}
package factory.method;
//工厂方法模式,顶级工厂接口
public interface CarFactory {
Car getCar();
}
具体的汽车工厂
package factory.method;
public class LslsFactory implements CarFactory{
@Override
public Car getCar() {
return new Lsls();
}
}
package factory.method;
public class WulingFactory implements CarFactory{
@Override
public Car getCar() {
return new Wuling();
}
}
package factory.method;
public class Bikefactory implements CarFactory{
@Override
public Car getCar() {
return new Bike();
}
}
package factory.method;
public class Bike implements Car{
@Override
public void name() {
System.out.println("我是新加的自行车!");
}
}
测试
package factory.method;
public class Test {
public static void main(String[] args) {
Car car1=new WulingFactory().getCar();
Car car2=new LslsFactory().getCar();
Car car3=new Bikefactory().getCar();
car1.name();
car2.name();
car3.name();
}
}
新加的自行车工厂
package factory.method;
public class Bikefactory implements CarFactory{
@Override
public Car getCar() {
return new Bike();
}
}
结果:
其他例子方便理解:
抽象工厂模式
围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类。
抽象工厂模式的优点
抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。
抽象工厂模式的缺点
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
适用场景
当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。
总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
package factory.abstract1;
//抽象产品工厂
public interface ProductFactory {
//生成手机
IphoneProduct iphoneproduct();
//生成路由器
IRouterProduct routerproduct();
}
package factory.abstract1;
//手机产品接口
public interface IphoneProduct {
void start();
void shutdown();
void callup();
void sendSMS();
}
package factory.abstract1;
//路由器产品接口
public interface IRouterProduct {
void start();
void shutdown();
void openwifi();
void setting();
}
package factory.abstract1;
public class HuaweiFactory implements ProductFactory{
@Override
public IphoneProduct iphoneproduct() {
return new HuaweiIphone();
}
@Override
public IRouterProduct routerproduct() {
return new HuaweiRouter();
}
}
package factory.abstract1;
public class XiaomiFactory implements ProductFactory{
@Override
public IphoneProduct iphoneproduct() {
return new XiaoMiphone();
}
@Override
public IRouterProduct routerproduct() {
return new Xiaomirouter();
}
}
package factory.abstract1;
public class HuaweiIphone implements IphoneProduct{
@Override
public void start() {
System.out.println("华为手机开机");
}
@Override
public void shutdown() {
System.out.println("华为手机关机");
}
@Override
public void callup() {
System.out.println("华为手机打电话");
}
@Override
public void sendSMS() {
System.out.println("华为手机发消息");
}
}
package factory.abstract1;
public class HuaweiRouter implements IRouterProduct{
@Override
public void start() {
System.out.println("华为路由器开机");
}
@Override
public void shutdown() {
System.out.println("华为路由器关机");
}
@Override
public void openwifi() {
System.out.println("华为路由器打开WiFi");
}
@Override
public void setting() {
System.out.println("华为路由器设置");
}
}
package factory.abstract1;
public class XiaoMiphone implements IphoneProduct{
@Override
public void start() {
System.out.println("小米手机开机");
}
@Override
public void shutdown() {
System.out.println("小米手机关机");
}
@Override
public void callup() {
System.out.println("小米手机打电话");
}
@Override
public void sendSMS() {
System.out.println("小米手机发消息");
}
}
package factory.abstract1;
public class Xiaomirouter implements IRouterProduct{
@Override
public void start() {
System.out.println("小米路由器开机");
}
@Override
public void shutdown() {
System.out.println("小米路由器关机");
}
@Override
public void openwifi() {
System.out.println("小米路由器打开WiFi");
}
@Override
public void setting() {
System.out.println("小米路由器设置");
}
}
package factory.abstract1;
public class Clint {
public static void main(String[] args) {
System.out.println("=================小米产品==============");
XiaomiFactory xiaomiFactory=new XiaomiFactory();
IphoneProduct iphoneproduct = xiaomiFactory.iphoneproduct();
iphoneproduct.callup();
iphoneproduct.sendSMS();
IRouterProduct iRouterProduct=xiaomiFactory.routerproduct();
iRouterProduct.openwifi();
iphoneproduct.sendSMS();
}
}
总结
简单工厂就是直接在工厂类里根据传入参数来创建接口的不同实现类的实例,工厂方法模式是有一个顶级工厂接口,只有工厂类在实现工厂接口时,才会创建实例,所以无需修改工厂,只需在添加工厂实现类时,创建实例即可。