Java学习-设计模式-抽象工厂模式
概述:
抽象工厂模式是另一个创建模式。
抽象工厂模式,也称为工厂的工厂,有一个工厂创建其他工厂。
当使用抽象工厂模式时,我们首先使用超级工厂创建工厂,然后使用创建的工厂创建对象。
理解:
这玩意就像是用简单工厂模式去获取一个简单工厂模式,然后再去获取想要的对象。
比如说,使用简单工厂模式去获取动物中的猫、狗两类,但是这次获取的不单单是猫和狗的对象,而是一个具有简单工厂模式的猫狗对象,由这个猫狗对象又生成了对应的猫(比如说折耳猫、橘猫等等)、狗(哈士奇、金毛等等)。
附:简单工厂的介绍链接。
核心结构
有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品。
工厂方法(Factory Method)模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法模式(Factory Method pattern)是最典型的模板方法模式(Template Method pattern)应用。
举例:
还是以动物来举例,从动物工厂中获取有关猫和狗的工厂,然后在相应的猫或者狗工厂中创建指定的猫或者狗相关的对象。
-
首先创建两个接口,一个与猫有关,一个与狗有关。
// 这个接口可有可无,这里是为了体现猫和狗都属于动物而创建 // 如果多个工厂有相同属性可以定义类似这样的接口 package Practices.Mode.Abstract_Factory.Animal; public interface Animal { public void introduce(); } // 与狗相关的接口 package Practices.Mode.Abstract_Factory.Animal; public interface Dog extends Animal { } // 与猫相关的接口 package Practices.Mode.Abstract_Factory.Animal; public interface Cat extends Animal { }
-
分别创建猫和狗的实现类
package Practices.Mode.Abstract_Factory.Animal; public class Folds implements Cat { public void introduce() { System.out.println("折耳猫"); } } package Practices.Mode.Abstract_Factory.Animal; public class Orange_cat implements Cat { public void introduce() { System.out.println("橘猫"); } } package Practices.Mode.Abstract_Factory.Animal; public class Golden_Retriever implements Dog { public void introduce() { System.out.println("金毛寻回犬"); } } package Practices.Mode.Abstract_Factory.Animal; public class Husky implements Dog { public void introduce() { System.out.println("哈士奇"); } }
-
创建一个抽象类来关联猫和狗(接口也行)
package Practices.Mode.Abstract_Factory.Factory; import Practices.Mode.Abstract_Factory.Animal.Cat; import Practices.Mode.Abstract_Factory.Animal.Dog; abstract class Animal_Factory { abstract Cat Create_Cat(String Dog_name); abstract Dog Create_Dog(String Dog_name); }
-
按照之前的简单工厂模式建立与猫和狗相关的工厂,并继承步骤三的抽象类,注意不属于自己的对象方法要返回null。
package Practices.Mode.Abstract_Factory.Factory; import Practices.Mode.Abstract_Factory.Animal.Cat; import Practices.Mode.Abstract_Factory.Animal.Dog; import Practices.Mode.Abstract_Factory.Animal.Folds; import Practices.Mode.Abstract_Factory.Animal.Orange_cat; public class Cat_Factory extends Animal_Factory { public Cat Create_Cat(String Dog_name){ if(Dog_name.equalsIgnoreCase("Orange_cat")){ // equalsIgnoreCase() 方法比较时不会考虑字符串的大小写 return new Orange_cat(); } else if(Dog_name.equalsIgnoreCase("Folds")){ return new Folds(); } else { return null; } }Dog Create_Dog(String Dog_name) { return null; } } package Practices.Mode.Abstract_Factory.Factory; import Practices.Mode.Abstract_Factory.Animal.Cat; import Practices.Mode.Abstract_Factory.Animal.Dog; import Practices.Mode.Abstract_Factory.Animal.Golden_Retriever; import Practices.Mode.Abstract_Factory.Animal.Husky; public class Dog_Factory extends Animal_Factory { Cat Create_Cat(String Dog_name) { return null; } Dog Create_Dog(String Dog_name){ if(Dog_name.equalsIgnoreCase("Golden_Retriever")){ // equalsIgnoreCase() 方法比较时不会考虑字符串的大小写 return new Golden_Retriever(); } else if(Dog_name.equalsIgnoreCase("Husky")){ // equalsIgnoreCase() 方法比较时不会考虑字符串的大小写 return new Husky(); } else { return null; } } }
-
创建动物相关的工厂,返回的是相应动物的工厂,而不是之前简单工厂模式的对象。
package Practices.Mode.Abstract_Factory.Factory; public class FactoryProducer { public static Animal_Factory Create_Animal(String animal_name){ if(animal_name.equalsIgnoreCase("Dog")){ // equalsIgnoreCase() 方法比较时不会考虑字符串的大小写 return new Dog_Factory(); } else if(animal_name.equalsIgnoreCase("Cat")){ // equalsIgnoreCase() 方法比较时不会考虑字符串的大小写 return new Cat_Factory(); } else { return null; } } }
-
创建测试类进行测试
package Practices.Mode.Abstract_Factory.Factory; import Practices.Mode.Abstract_Factory.Animal.Dog; // 抽象工厂练习 public class Animal_main { public static void main(String[] args) { // 1. 首先通过动物工厂创建有关狗类的工厂 Animal_Factory dog_Factory = FactoryProducer.Create_Animal("Dog"); // 2. 通过狗类的工厂创建与狗有关的对象 Dog goldenRetriever = dog_Factory.Create_Dog("Golden_Retriever"); Dog husky = dog_Factory.Create_Dog("Husky"); // 3. 测试返回的对象 goldenRetriever.introduce(); husky.introduce(); } }
**踩坑之一:在工厂生产类中时,没有和抽象类在同一包下,竟然会报错…还是用接口好了。 **
练习总结:
练习感觉不对,感觉还是没有足够解耦,与狗相关的工厂中,为什么会还有与猫相关的方法。我感觉定义一个空接口,然后让这些子工厂去实现这个接口,不知道这样能不能去除这重耦合,有时间测试一下,暂时真的不想整了。