1.工厂方法模式概述:
工厂方法模式(Pattern:Factory Method)属于创建型模式,其意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,将核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品(例如下面的例子中,新建的一个中学生的志愿者对象)。
2.工厂方法模式的角色及其职责:
(1)抽象产品角色[Product]:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。//可以理解为产品有哪些特点
(2)具体产品角色[Concrete Product]:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。//可以理解为产品具体能干什么,干的结果怎么样
(3)抽象工厂角色[Creator]:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。//可以理解为一个大工厂能生产什么样的产品
(4)具体工厂角色[Concrete Creator]:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。//可以理解为一个具体的已经存在的工厂,有生产哪些产品的机器(具体产品角色)
3.工厂方法模式的设计原则及UML类图:
(1)设计原则:
①依赖倒置原则:要依赖抽象,不要依赖具体类。
用依赖倒置原则设计的系统,使得对象的实现从使用中解耦,对象的使用是在Creator,实现却在ConcreteCreator中,Creator只有Product的引用,Creator与ConcreteProduct松耦合,这种设计拥有很强的扩展性、弹性和可维护性。
(2)UML类图:
4.Java案例代码:
(1)抽象产品角色(产品干哪些活):
1 package FactoryMethodPattern; 2 3 //定义一个有雷锋精神的人,并定义他又那些能力,如打扫,洗衣,买米 4 public abstract class LeiFeng { 5 public abstract void Sweep(); 6 7 public abstract void Wash(); 8 9 public abstract void BuyRice(); 10 11 }
(2)具体产品角色(产品具体能干什么,干的结果怎么样):
1 package FactoryMethodPattern; 2 3 //社区志愿者有雷锋精神,并能做的实际工作 4 public class Volunteer extends LeiFeng { 5 6 @Override 7 public void Sweep() { 8 System.out.print("社区志愿者帮忙打扫,能干8小时,因为不用上班"); 9 10 } 11 12 @Override 13 public void Wash() { 14 System.out.print("社区志愿者帮忙洗衣服,能干4小时,因为太累"); 15 16 } 17 18 @Override 19 public void BuyRice() { 20 System.out.print("社区志愿者帮忙买米,买一次就够吃了"); 21 22 } 23 24 } 25 26 //学雷锋的大学生 27 class Undergraduate extends LeiFeng { 28 29 @Override 30 public void Sweep() { 31 System.out.print("大学生帮忙打扫,能干4个小时,还要上课;"); 32 33 } 34 35 @Override 36 public void Wash() { 37 System.out.print("大学生不用洗衣服,帮忙晒被子;"); 38 39 } 40 41 @Override 42 public void BuyRice() { 43 System.out.print("大学生帮忙买米,随便可以带点水果;"); 44 45 } 46 47 }
(3)抽象工厂角色(一个大工厂能生产什么样的产品):
1 package FactoryMethodPattern; 2 3 //雷锋工厂 4 public interface IFactory { 5 LeiFeng CreateLeiFeng(); 6 }
(4)具体工厂角色(具体的已经存在的工厂,有生产哪些产品的机器):
1 package FactoryMethodPattern; 2 3 //社区志愿者工厂 4 public class VolunteerFactory implements IFactory { 5 @Override 6 public LeiFeng CreateLeiFeng() { 7 return new Volunteer(); 8 } 9 10 } 11 12 //学雷锋的大学生工厂 13 class UndergraduateFactory implements IFactory { 14 @Override 15 public LeiFeng CreateLeiFeng() { 16 return new Undergraduate(); 17 } 18 19 }
(5)客户端测试代码:
1 package FactoryMethodPattern; 2 3 public class Test { 4 public static void main(String[] args) { 5 //要换成'社区志愿者',修改这里就可以 6 IFactory factory = new UndergraduateFactory(); 7 LeiFeng student = factory.CreateLeiFeng(); 8 9 student.Sweep(); 10 student.Wash(); 11 student.BuyRice(); 12 System.out.println(" --------------------------"); 13 14 IFactory factory2 = new VolunteerFactory(); 15 LeiFeng volunteer = factory2.CreateLeiFeng(); 16 17 volunteer.Sweep(); 18 volunteer.Wash(); 19 volunteer.BuyRice(); 20 } 21 }
(6)客户端测试代码结果:
5.工厂方法模式的优缺点及使用场景:
(1)优点:
①符合开闭原则,具有很强的的扩展性、弹性和可维护性。扩展时只要添加一个ConcreteCreator,而无须修改原有的ConcreteCreator,因此维护性也好。解决了简单工厂对修改开放的问题。
②使用了依赖倒置原则,依赖抽象而不是具体,使用(客户)和实现(具体类)松耦合。
③客户只需要知道所需产品的具体工厂,而无须知道具体工厂的创建产品的过程,甚至不需要知道具体产品的类名。
(2)缺点:
①一个具体产品对应一个类,当具体产品过多时会使系统类的数目过多,增加系统复杂度。
②每增加一个产品时,都需要一个具体类和一个具体创建者,使得类的个数成倍增加,导致系统类数目过多,复杂性增加。
③对简单工厂,增加功能修改的是工厂类;对工厂方法,增加功能修改的是客户端。
(3)应用场景:
①当需要一个对象时,我们不需要知道该对象所对应的具体类,只要知道哪个具体工厂可以生成该对象,实例化这个具体工厂即可创建该对象。
②类的数目不固定,随时有新的子类增加进来,或者是还不知道将来需要实例化哪些具体类。
③定义一个创建对象接口,由子类决定要实例化的类是哪一个;客户端可以动态地指定工厂子类创建具体产品。
————————————————
版权声明:本文为CSDN博主「LRB_Len」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39588630/java/article/details/80478349