初识设计模式之简单工厂模式、工厂方法模式、抽象工厂模式
工厂顾名思义就是生产产品的意思,根据产品是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。该模式用于封装和管理对象的创建,是一种创建型模式。
1. 简单工厂模式
首先,我们有一个服装制造厂,有一张服装设计原稿。现在,我们需要根据各个经销商的要求制造出不同颜色的衣服。
-
Clothes接口:即服装设计原稿
public interface Clothes { void getName(); }
-
BlueClothes类:根据图纸制造出来的蓝色的衣服
public class BlueClothes implements Clothes{ public void getName() { System.out.print("BlueClothes"); } }
-
RedClothes类:根据图纸制造出来的蓝色的衣服
public class RedClothes implements Clothes{ public void getName() { System.out.print("RedClothes"); } }
-
GreenClothes类:根据图纸制造出来的蓝色的衣服
public class GreenClothes implements Clothes{ public void getName() { System.out.print("GreenClothes"); } }
-
SimpleClothesFactory类:一个简单的服装制造厂
public class SimpleClothesFactory { public Clothes CreateClothes(String orderColor) { Clothes Clothes = null; if (orderColor.equals("blue")) { Clothes = new BlueClothes(); } else if (orderColor.equals("red")) { Clothes = new RedClothes(); } else if (orderColor.equals("green")) { Clothes = new GreenClothes(); } return Clothes; } //开工开工 public static void main(String[] args) { SimpleClothesFactory scf = new SimpleClothesFactory(); scf.CreateClothes("red").getName(); //拿到红色的订单后,输出"RedClothes" } }
简单工厂模式的优点:
- 工厂类是整个模式的关键。包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的。明确了各自的职责和权利,有利于整个软件体系结构的优化。
简单工厂模式的缺点:
- 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
- 当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求。这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。
- 这些缺点在工厂方法模式中得到了一定的克服。
可以考虑的应用场景:
- 工厂类负责创建的对象比较少;
- 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
- 由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
2. 工厂方法模式
那么问题来了,在我们使用简单工厂模式时,当我们的服装厂生意做大了,吸引了无数经销商前来订单,这时我们厂里只能生产红、绿、蓝颜色的衣服。如果我们想要接下这批订单,那我们就要对原工厂进行改造,那就会消耗大量的人力物力了。这时,工厂方法模式就登场了!
-
Clothes接口:服装设计原稿
-
YellowClothes类:按稿件设计出来的黄色衣服
-
WhiteClothes类:按稿件设计出来的白色衣服
-
ClothesFactory接口:服装厂原型,建造具体服装厂时的标准
-
YellowClothesFactory类:生产黄色衣服的工厂
-
WhiteClothesFactory类:生产白色衣服的工厂
-
Work类:工厂开工(启动类)
interface Clothes{ void showTag(); } class YellowClothes implements Clothes{ public void showTag() { System.out.println("YellowClothes"); } } class WhiteClothes implements Clothes{ public void showTag() { System.out.println("WhiteClothes"); } } interface ClothesFactory{ public abstract Clothes produce(); } class YellowClothesFactory implements ClothesFactory{ public Clothes produce() { return new YellowClothes(); } } class WhiteClothesFactory implements ClothesFactory{ public Clothes produce() { return new WhiteClothes(); } } public class Work { public static void main(String[] args){ ClothesFactory ycf = new YellowClothesFactory(); ycf.produce().showTag(); //输出YellowClothes ClothesFactory wcf = new WhiteClothesFactory(); wcf.produce().showTag(); //输出WhiteClothes } }
如此这般,在我们接受到新订单时我们只需要新建一个小工厂就可以了。不需要对建好的工厂进行改造。它能更好的符合开闭原则的要求。
工厂方法模式的优点:
- 用户只需要关心产品对应的工厂,甚至无需关心创建细节或具体产品类的类名。
- 基于工厂角色和产品的多态性设计是工厂模式的关键。它能自主决定如何创建哪种产品对象,而创建细节都封装在具体工厂内部。
- 在系统要添加新的产品时,无需修改抽象工厂和抽象产品提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,只要添加一个具体工厂和具体产品即可,从而提高系统的可扩展性(符合开闭原则)
工厂方法模式的缺点:
- 在添加新产品时,要编写新的具体产品类,并要提供与之对应的具体工厂类。系统软件个数也成对增加,从而增加了系统的复杂度,带来更多开销。
- 由于系统的可扩展性,在客户端中要引入抽象层进行定义,从而增加了系统的抽象性和理解难度。
3. 抽象工厂模式
工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。
让我们回到我们的服装厂继续分析,现在,我们已经不满足于衣服业务啦,我们要进军裤子生产届,那么问题来了,我们只有衣服生产厂,怎么办呢?我们现在迫切需要一种多个产品族结构的解决方案。
-
Clothes接口:衣服设计原稿
-
YellowClothes类:按稿件设计出来的黄色衣服
-
WhiteClothes类:按稿件设计出来的白色衣服
-
Trousers接口:裤子设计原稿
-
YellowTrousers类:按稿件设计出来的黄色裤子
-
WhiteTrousers类:按稿件设计出来的白色裤子
-
AbstractFactory抽象类:服装厂原型,建造具体服装厂时的标准
-
YellowFactory类:拥有黄色原料的工厂
-
WhiteFactory类:拥有白色原料的工厂
-
Work类:工厂开工(启动类)
//衣服原稿 interface Clothes{ void showClothesTag(); } //裤子原稿 interface Trousers{ void showTrousersTag(); } //衣服原稿制作出来的黄色衣服 class YellowClothes implements Clothes{ public void showClothesTag() { System.out.println("YellowClothes"); } } //衣服原稿制作出来的白色衣服 class WhiteClothes implements Clothes{ public void showClothesTag() { System.out.println("WhiteClothes"); } } //衣服原稿制作出来的黄色裤子 class YellowTrousers implements Trousers{ public void showTrousersTag() { System.out.println("YellowTrousers"); } } //衣服原稿制作出来的白色裤子 class WhiteTrousers implements Trousers{ public void showTrousersTag() { System.out.println("WhiteTrousers"); } } //能生产衣服和裤子的工厂 abstract class AbstractFactory{ public abstract Clothes produceClothes(); public abstract Trousers produceTrousers(); } //拥有黄色原料的工厂 class YellowFactory extends AbstractFactory{ public Clothes produceClothes() { return new YellowClothes(); } public Trousers produceTrousers() { return new YellowTrousers(); } } //拥有白色原料的工厂 class WhiteFactory extends AbstractFactory{ public Clothes produceClothes() { return new WhiteClothes(); } public Trousers produceTrousers() { return new WhiteTrousers(); } } //启动类 public class Work { public static void main(String[] args) { AbstractFactory yf = new YellowFactory(); AbstractFactory wf = new WhiteFactory(); System.out.println("黄色原料工厂正在生产:"); yf.produceClothes().showClothesTag(); yf.produceTrousers().showTrousersTag(); System.out.println("白色原料工厂正在生产:"); wf.produceClothes().showClothesTag(); wf.produceTrousers().showTrousersTag(); } }
如此这般,我们就可以正式进军裤子制造届啦。
抽象工厂模式的优点:
- 分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,它们不出现在客户代码中。
- 易于交换产品系列。一个具体工厂类只在初始化时出现一次,这使得改变一个应用的具体工厂变得很容易,只需改变具体的工厂即可使用不同的产品配置。
- 有利于产品的一致性。当一个系列的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要,而抽象工厂很容易实现这一点。
抽象工厂模式的缺点:
- 难以支持新种类的产品。因为抽象工厂接口确定了可以被创建的产品集合,所以难以扩展抽象工厂以生产新种类的产品。
可以考虑使用的场景:
- 一个系统要独立于它的产品的创建、组合和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 需要强调一系列相关的产品对象的设计以便进行联合使用时。
- 提供一个产品类库,而只想显示它们的接口而不是实现时。
以上就是我对这三个模式的简单认识啦,也是作为个人的学习总结,仅供参考!
如有错误,万望指正。