工厂模式部分内容主要包括简单工厂模式、工厂方法模式、抽象工厂模式。下面各个例子省略了main方法。
- 简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式。简单工厂方法使用比较简单,创建相应的工厂类,执行方法时传入不同的参数,然后生成不同的对象,如下面例子所示。
public interface SportsMan { public void motion(); }
public class FootballPlayer implements SportsMan { @Override public void motion() { System.out.println("踢足球"); } }
public class Hoopman implements SportsMan { @Override public void motion() { System.out.println("打篮球"); } }
public class SportsManFactory { public SportsMan getSprotsMan(String name) { SportsMan sportsMan = null; switch (name) { case "hoopman": sportsMan = new Hoopman(); break; case "footballplayer": sportsMan = new FootballPlayer(); break; default: sportsMan = null; } return sportsMan; } }
优点:实现了对象创建和使用的分离,客户端无需知道对象的创建过程,只要传入相应的参数,那么就可以拿到对应的结果,可以通过在调用处引入配置(xml文件、数据库等)来实现参数的配置。
缺点:工厂类的功能过于重要,有过的if、else判断,对于新增的产品,同时也要加入if、else判断,不适合太多产品的创建,如果产品经常新增,那么修改次数较大, 不符合开闭原则。 - 工厂方法模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。为每个产品创建自己的实现工厂,将工厂和产品都抽出成为接口。工厂方法模式让一个类的实例化延迟到其子类。可以理解为,最初创建了一个工厂,工厂规模比较小,什么牌子的都可以进行生产,但是随着工厂规模的增大,工厂也需要进行拆分,比如根据品牌进行拆分。工厂变为了一个抽象,其功能为生产鞋子(抽象)。实现工厂的子类有耐克工厂、李宁工厂等,都继承了生产鞋子方法,分别生产耐克鞋子,李宁鞋子。
public interface SportsMan { public void motion(); }
public interface SportsManFactory { public SportsMan getSprotsMan(); }
public class Hoopman implements SportsMan { @Override public void motion() { System.out.println("打篮球"); } }
public class HoopmanFactory implements SportsManFactory { @Override public SportsMan getSprotsMan() { return new Hoopman(); } }
public class FootballPlayer implements SportsMan { @Override public void motion() { System.out.println("踢足球"); } }
public class FootballPlayerFactory implements SportsManFactory { @Override public SportsMan getSprotsMan() { return new FootballPlayer(); } }
优点:使用对象处只需要关心对应产品的工厂,对于新增的产品,那么只要通过修改配置获取新增产品的工厂就可以了,新增产品时,不需要修改公共的工厂对象,只要新增一个自己的产品工厂,完全实现了开闭原则。
缺点:每次新增产品都要新增两个类,代码比较繁琐。 - 抽象工厂模式::提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。个人感觉抽象工厂更像是对工厂方法模式的归类。比如李宁、耐克品牌都有生产鞋子、上衣、裤子的功能,如果还是按照工厂方法模式,李宁需要3个产品类和3个产品工厂类,耐克同样,但是抽象工厂方法可以对品牌进行归类,比如工厂具有生产鞋子、上衣、裤子的功能,李宁工厂生产李宁鞋子、李宁上衣、李宁裤子,耐克同样;避免了客户端大量代码,同时减少了类的创建。
public interface SportsFactory { public SportsShoes createSportsShoes(); public SportsClothes createSportsClothes(); }
public interface SportsClothes { }
public interface SportsShoes { }
public class LiNingFactory implements SportsFactory { @Override public SportsShoes createSportsShoes() { return new LiNingShoes(); } @Override public SportsClothes createSportsClothes() { return new LiNingClothes(); } }
public class LiNingClothes implements SportsClothes {
}
public class LiNingShoes implements SportsShoes { }
public class NikeFactory implements SportsFactory{ @Override public SportsShoes createSportsShoes() { return new NikeShoes(); } @Override public SportsClothes createSportsClothes() { return new NikeClothes(); } }
public class NikeClothes implements SportsClothes { }
public class NikeShoes implements SportsShoes { }
优点:符合开闭原则,减少了客户端大量代码的引用,减少了工厂类的创建。
缺点:对于新增分类类型比较方便,只要创建相应的产品类和产品工厂就可以,但是如果抽象接口中新增了产品类型,那么不但为每个分了创建相应的产品类,还要修改每个产品工厂类。