抽象工厂模式:正如其名字一样,非常抽象,这啥概念的我也不多说了,但是抽象工厂模式的功能却十分强大。下面我主要通过对比三种工厂模式来进行学习。
1.简单工厂模式 (Simple Factory)
定义:只有一个工厂类,通过想创建方法中传入不同的参数,来生产不同的产品。
首先定义一个产品类的共同接口
public interface Product {
//声明类所需继承的共同接口,也可以是抽象类
}
产品类A
public class ProductA implements Product {
public ProductA() {
System.out.println("ProductA");
}
}
产品类B
public class ProductB implements Product {
public ProductB() {
System.out.println("ProductB");
}
}
工厂类
public class Factory {
//可以在工厂类中添加任何你所需要的逻辑
public static Product create(String str)
{
//生成ProductA
if(str.equalsIgnoreCase("ProductA"))
{
return new ProductA();
}
else
//生成ProductB
if(str.equalsIgnoreCase("ProductB"))
{
return new ProductB();
}
return null;
}
}
客户端
public class Client {
public static void main(String[] args) {
//调用Factory的静态方法生成所要的类
Factory.create("productA");
Factory.create("ProductB");
}
}
假如我们又要添加一个新的产品类C呢?
优点:能够根据外界给定的信息,决定应该创建哪个具体类对象。用户在使用时可以无需了解这些对象是如何创建的,有利于整个软件体系结构的优化。
缺点:违背面向对象设计的“开闭原则”和“单一职责原则”。因为我们每增加一个产品就要去修改工厂类的代码,而且一个工厂生产各式各样的产品显然职责不单一
2.工厂方法模式
定义:定义一个创建对象的接口(抽象工厂类),让其子类(具体工厂类)去决定实例化哪个类(具体产品类)。一个工厂实现一种产品,一对一的关系。
产品类中增加了ProductC
public class ProductC implements Product {
public ProductC() {
System.out.println("productC");
}
}
声明工厂接口
public interface Factory {
//声明产生产品类的方法
public Product createProduct();
}
分别产生Product的Factory
public class FactoryA implements Factory {
//实现工厂类的方法生成产品类A
public Product createProduct()
{
return new ProductA();
}
}
public class FactoryB implements Factory {
//实现工厂类的方法生成产品类B
public Product createProduct()
{
return new ProductB();
}
}
public class FactoryC implements Factory {
//实现工厂类的方法生成产品类C
public Product createProduct()
{
return new ProductC();
}
}
客户端
public class Client {
public static void main(String[] args) {
Factory factory;
factory = new FactoryA();
factory.createProduct();
factory = new FactoryB();
factory.createProduct();
factory = new FactoryC();
factory.createProduct();
}
}
结论:工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。但是这还是有缺点的,如果产品类过多,我们就要生成很多的工厂类。假设现在需要针对每种产品生产对应的赠品,难道我们要新增一个Gift的生产工厂吗?其实没有必要,因为在这个场景下,每种产品必须附带了赠品,所以我们可以利用原有的工厂来生产赠品族。对于这种情况我们可以采用抽象工厂模式。
3.抽象工厂模式
定义:提供一个创建一系列相关或者相互依赖产品的接口,而无需制定他们的具体类,一对多的关系。抽象工厂模式是工厂方法模式的升级版
新增gift这个产品
public interface Gift {
//声明产品赠品的接口,当然也可以是抽象类,同样为了简单就不声明方法了
}
public class GiftA implements Gift {
public GiftA()
{
System.out.println("GiftA");
}
}
public class GiftB implements Gift {
public GiftB()
{
System.out.println("GiftB");
}
}
Fatory
public interface Factory {
public Product createProduct();
public Gift createGift();
}
public class FactoryA implements Factory {
@Override
public Product createProduct()
{
return new ProductA();
}
@Override
public Gift createGift()
{
return new GiftA();
}
}
public class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
@Override
public Gift createGift() {
return new GiftB();
}
}
客户端
public class Client {
public static void main(String[] args) {
Factory factory;
factory = new FactoryA();
factory.createProduct();
factory.createGift();
factory = new FactoryB();
factory.createProduct();
factory.createGift();
}
}
结论:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。抽象工厂接口,应该包含所有的产品创建的抽象方法,我们可以定义实现不止一个接口,一个工厂也可以生产不止一种产品类,和工厂方法模式一样,抽象工厂模式同样实现了开发封闭原则
补充:需要注意的是学习最忌讳生搬硬套,为了设计模式而设计。设计模式主要解决的就是设计模式的六大原则,只要我们设计的代码遵循这六大原则,那么就是优秀代码。
另附设计模式六大原则
1、单一职责原则(Single Responsibility Principle)
定义 : 应该有且只有一个原因引起类的变化
注意 : 这里的类不光指类,也适用于方法和接口,比如我们常说的一个方法实现一个功能
2、里氏代换原则(Liskov Substitution Principle)
3、依赖倒置原则(Dependence Inversion Principle)
定义 : 依赖倒置原则包含三个含义
高层模块不应该依赖低层模块,两者都应该依赖其抽象
抽象不应该依赖细节
细节应该依赖抽象
4、接口隔离原则(Interface Segregation Principle)
5、迪米特法则(Demeter Principle)
定义 : 迪米特法则也叫最少知识原则,含义是 一个对象应该对其他对象有最少的了解,这个应该很好理解,就是降低各模块之间的耦合
6、开闭原则(Open Close Principle)
定义 : 一个软件实体如类,模块和函数应该对扩展开放,对修改关闭,开闭原则也是其他五个原则的基石
网友评论