在之前的Q&A里面讨论过设计模式的学习,最近准备系统学习一下设计模式,于是买了一本《大话设计模式》结合网上的一些博客来学习,我觉得里面有句话说的很好学习设计模式“重要的不是你将来会不会用到这些模式,而是通过这些模式让你找到‘封装变化’,‘对象间松散耦合’,‘针对接口编程’的感觉,从而设计出易维护、易扩展、易服用、灵活性好的程序”,今天也听到有人说这个本书是“修改代码的艺术”,感觉也有那么一点道理,只不过设计模式的目的是设计出易维护、易扩展、易服用、灵活性好的代码。
今天总结一些工厂模式:简单工厂模式,工厂方法模式,抽象工厂模式。
简单工厂模式(静态工厂模式):实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。简单工厂模式一个实例的UML图如下:
该模式中的角色有:
1.工厂角色:这个是简单工厂模式的核心,根据用户传入的参数不同,动态创建不同产品的对象实例,
2.抽象产品角色:如图中的运算类,负责描述所有具体实例的公共接口
3.具体产品角色:如图中的加法类、减法类、乘法类、除法类,这些是工厂类中要创建的实例,它们实现具体方法。
优点:工厂类中包含必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
缺点:很明显所以实例的创建都聚合在工厂类中,那么在工厂内里面就形成了高内聚,如果要增加新的实例的话,需要对工厂类进行修改,这个就违背了“开放-封闭原则”(对扩展开发,对修改封闭)。
工厂方法模式:在简单工厂模式中集中有工厂类创建实例可以由工厂方法模式中的工厂子类来完成。该模式的UML图如下所示:
该模式中的角色有:
1.抽象工厂角色:这个是工厂方法模式的核心,与应用程序无关,是具体工厂角色必须继承的接口或者必须继承的父类。
2.具体工厂角色:比如加法工厂、减法工厂、乘法工厂、除法工厂,含有与具体业务逻辑有关的代码。由应用程序调用以创建具体对应的产品对象。
3.抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般由抽象类或者接口来实现。
4.具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
给一个简单的例子:
- //抽象产品
- abstract class Car{
- private String name;
- public abstract void drive();
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- //具体产品
- class Benz extends Car{
- public void drive(){
- System.out.println(this.getName()+"----go-----------------------");
- }
- }
- class Bmw extends Car{
- public void drive(){
- System.out.println(this.getName()+"----go-----------------------");
- }
- }
- //抽象工厂
- abstract class Driver{
- public abstract Car createCar(String car) throws Exception;
- }
- //具体工厂(每个具体工厂负责一个具体产品)
- class BenzDriver extends Driver{
- public Car createCar(String car) throws Exception {
- return new Benz();
- }
- }
- class BmwDriver extends Driver{
- public Car createCar(String car) throws Exception {
- return new Bmw();
- }
- }
- //老板
- public class Boss{
- public static void main(String[] args) throws Exception {
- Driver d = new BenzDriver();
- Car c = d.createCar("benz");
- c.setName("benz");
- c.drive();
- }
- }
该模式的角色有:
1.抽象工厂角色:这个是工厂方法模式的核心,与应用程序无关,是具体工厂角色必须继承的接口或者必须继承的父类。
2.具体工厂角色:比如加法工厂、减法工厂、乘法工厂、除法工厂,含有与具体业务逻辑有关的代码。由应用程序调用以创建具体对应的产品对象。
3.抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般由抽象类或者接口来实现。
4.具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
从上面的角色可以看出来,其实抽象工厂模式跟工厂方法模式是很相似的,他们不同点如下:工厂方法模式:针对一个产品等级结构,一个抽象产品类可以派生出多个具体产品类,一个抽象工厂类可以派生出多个具体工厂类,每个具体工厂类只能生产一个具体产品类的实例。
抽象工厂模式:针对多个产品等级结构,有多个抽象产品类,每个抽象产品类可以派生出多个具体产品类,一个抽象工厂类可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。
给出一个简单代码例子方便理解:
- //抽象产品(Bmw和Audi同理)
- abstract class BenzCar{
- private String name;
- public abstract void drive();
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- //具体产品(Bmw和Audi同理)
- class BenzSportCar extends BenzCar{
- public void drive(){
- System.out.println(this.getName()+"----BenzSportCar-----------------------");
- }
- }
- class BenzBusinessCar extends BenzCar{
- public void drive(){
- System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
- }
- }
- abstract class BmwCar{
- private String name;
- public abstract void drive();
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- class BmwSportCar extends BmwCar{
- public void drive(){
- System.out.println(this.getName()+"----BmwSportCar-----------------------");
- }
- }
- class BmwBusinessCar extends BmwCar{
- public void drive(){
- System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
- }
- }
- abstract class AudiCar{
- private String name;
- public abstract void drive();
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- class AudiSportCar extends AudiCar{
- public void drive(){
- System.out.println(this.getName()+"----AudiSportCar-----------------------");
- }
- }
- class AudiBusinessCar extends AudiCar{
- public void drive(){
- System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
- }
- }
- //抽象工厂
- abstract class Driver3{
- public abstract BenzCar createBenzCar(String car) throws Exception;
- public abstract BmwCar createBmwCar(String car) throws Exception;
- public abstract AudiCar createAudiCar(String car) throws Exception;
- }
- //具体工厂
- class SportDriver extends Driver3{
- public BenzCar createBenzCar(String car) throws Exception {
- return new BenzSportCar();
- }
- public BmwCar createBmwCar(String car) throws Exception {
- return new BmwSportCar();
- }
- public AudiCar createAudiCar(String car) throws Exception {
- return new AudiSportCar();
- }
- }
- class BusinessDriver extends Driver3{
- public BenzCar createBenzCar(String car) throws Exception {
- return new BenzBusinessCar();
- }
- public BmwCar createBmwCar(String car) throws Exception {
- return new BmwBusinessCar();
- }
- public AudiCar createAudiCar(String car) throws Exception {
- return new AudiBusinessCar();
- }
- }
- //老板
- public class BossAbstractFactory {
- public static void main(String[] args) throws Exception {
- Driver3 d = new BusinessDriver();
- AudiCar car = d.createAudiCar("");
- car.drive();
- }
- }
缺点:在增加产品的时候增加的代码量也是比较多的。需要增加具体工厂类,抽象产品类,具体产品类三个类。
可以使用简单工厂来改进抽象工厂,大家可以尝试一下。