[设计模式/Java] 设计模式之抽象工厂模式【12】
概述:抽象工厂模式
模式定义
- 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。
- 该超级工厂又称为其他工厂的工厂。
- 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通
过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
- 核心思路:
- 在一个产品族中定义多个产品,由具体工厂实现创建这些产品的方法。
- 关键代码
在一个工厂中聚合多个同类产品的创建方法。
- 产品族 vs 产品种类
- 产品族:一个品牌下面的所有产品;例如华为下面的手机,路由器,电脑 称为华为的产品族;
- 产品种类:多个品牌下面的同种产品;例如华为和小米下面的手机 称为一个产品种类;

模式的组成
- 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。
- 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。
- 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。
- 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
抽象工厂模式通常涉及一族相关的产品,每个具体工厂类负责创建该族中的具体产品。
客户端通过使用抽象工厂接口来创建产品对象,而不需要直接使用具体产品的实现类。
模式特点
优点
- 
确保同一产品族的对象一起工作。 
- 
客户端不需要知道每个对象的具体类,简化了代码。 
- 
一个(品牌的)产品族中的多个产品对象被设计成一起工作时,它能保证客户端始终只使用同一品牌/产品族中的产品对象 
将一个系列的产品统一一起创建
缺点
- 扩展产品种类非常困难。增加一个新的产品种类需要修改抽象工厂和所有具体工厂的代码。
- 产品种类的扩展非常困难,要增加一个系列的某一产品,既要修改工厂抽象类里加代码,又修改具体的实现类里面加代码;
- 增加了系统的抽象性和理解难度;
适用场景
- 一系列相关产品对象(属于同一产品族)一起创建时需要大量的重复代码;
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现;
抽象工厂模式符合依赖抽象原则
- 创建对象实例时,不要直接
new一个对象, 而是把创建对象的动作放在一个工厂的方法中;- 不要让类继承具体类,而是继承抽象类或者是实现接口;
- 不要覆盖基类中已经实现的方法;
案例实践
案例 : 手机产品、路由器产品
- 
有手机和路由器两种产品,有华为和小米两种品牌,两种品牌都可以生产手机和路由器; 
- 
有手机和路由器两种产品,定义2个接口; 
- 
小米和华为都可以生产这两种产品,所以有4个产品实现类; 
- 
现在需要创建华为和小米的工厂类,先将工厂类进行抽象,里面有创建两个产品的方法,返回的是产品的接口类;(抽象工厂类) 
- 
创建华为和小米的工厂实现类,继承工厂类接口,实现创建各自产品的方法;(工厂实现类) 
- 
客户端调用时,直接用工厂接口类创建需要的工厂,拿到对应的产品; 

IPhoneProduct / IRouterProduct : 抽象产品接口
- 手机产品接口
public interface IPhoneProduct {
    //开机
    void start();
    //关机
    void shutdown();
    //打电话
    void callup();
    //发邮件
    void sendSMS();
}
- 路由器产品接口
public interface IRouterProduct {
    //开机
    void start();
    //关机
    void shutdown();
    //打开wifi
    void openwifi();
    //设置
    void setting();
}
不同工厂的产品族下的具体产品
HuaweiPhone / HuaweiRouter : 华为产品族
- HuaweiPhone
public class HuaweiPhone implements IPhoneProduct {
    @Override
    public void start() {
	System.out.println("开启华为手机");
    }
    @Override
    public void shutdown() {
	System.out.println("关闭华为手机");
    }
    @Override
    public void callup() {
	System.out.println("华为手机打电话");
    }
    @Override
    public void sendSMS() {
	System.out.println("华为手机发邮件");
    }
}
- HuaweiRouter
华为路由器实现类
public class HuaweiRouter implements IRouterProduct {
    @Override
    public void start() {
        System.out.println("开启华为路由器");
    }
    @Override
    public void shutdown() {
	System.out.println("关闭华为路由器");
    }
    @Override
        public void openwifi() {
	System.out.println("打开华为wifi");
    }
    @Override
    public void setting() {
	System.out.println("设置华为路由器");
    }
}
XiaomiPhone / XiaomiRouter : 小米产品族
- XiaomiPhone
小米手机实现类
public class XiaomiPhone implements IPhoneProduct {
    @Override
    public void start() {
	System.out.println("开启小米手机");
    }
    @Override
    public void shutdown() {
	System.out.println("关闭小米手机");
    }
    @Override
    public void callup() {
	System.out.println("小米手机打电话");
    }
    @Override
    public void sendSMS() {
	System.out.println("小米手机发邮件");
    }
}
- XiaomiRouter
小米路由器实现类
public class XiaomiRouter implements IRouterProduct {
    @Override
    public void start() {
	System.out.println("开启小米路由器");
    }
    @Override
    public void shutdown() {
	System.out.println("关闭小米路由器");
    }
    @Override
    public void openwifi() {
	System.out.println("打开小米wifi");
    }
    @Override
    public void setting() {
	System.out.println("设置小米路由器");
    }
}
HuaweiFactory / XiaomiFactory : 不同工厂的具体工厂类
华为和小米工厂实现类,继承工厂接口
HuaweiFactory
华为工厂实现类
public class HuaweiFactory implements IProductFactory {
    @Override
    public IPhoneProduct phoneProduct() {
	return new HuaweiPhone();
    }
    @Override
    public IRouterProduct routerProduct() {
	return new HuaweiRouter();
    }
}
XiaomiFactory
小米工厂实现类
public class XiaomiFactory implements IProductFactory {
    @Override
    public IPhoneProduct phoneProduct() {
    	return new XiaomiPhone();
    }
    @Override
    public IRouterProduct routerProduct() {
	return new XiaomiRouter();
    }
}
Client
客户端,通过
IProductFactory创建各自的工厂,通过工厂拿到对应的产品
public class Client {
    public static void main(String[] args) {
        
	System.out.println("============小米产品============");
	//创建小米工厂
	IProductFactory xiaomiFactory = new XiaomiFactory();
	//生产小米手机
	IPhoneProduct xiaomiPhone = xiaomiFactory.phoneProduct();
	xiaomiPhone.start();
	xiaomiPhone.sendSMS();
	//生产小米路由器
	IRouterProduct xiaomiRouter = xiaomiFactory.routerProduct();
	xiaomiRouter.openwifi();
	xiaomiRouter.setting();
	System.out.println("============华为产品============");
	//创建华为工厂
	IProductFactory huaweiFactory = new HuaweiFactory();
	//生产华为手机
	IPhoneProduct huaweiPhone = huaweiFactory.phoneProduct();
	huaweiPhone.start();
	huaweiPhone.sendSMS();
	//生产华为路由器
	IRouterProduct huaweiRouter = huaweiFactory.routerProduct();
	huaweiRouter.openwifi();
	huaweiRouter.setting();
    }
}
延申:新增产品族 or 新增产品种类?
抽象工厂模式的实现就是这样,还记得前面讲的产品族和产品等级的概念吗,如果新增一个产品族或产品种类会怎样?
新增产品族(新增品牌)
- 如果扩展一个产品族,例如新增一个手机,也就是说新增一个品牌来生产手机,如下图所示(黄色字体为新增一个产品等级需要做的事),新增一个产品族不用修改原来的代码,符合OCP原则(开闭原则),这是非常舒服的;

新增产品种类
- 我们会发现,拓展一个产品种类是【非常困难】的,例如产品族中新增一个笔记本电脑,也就是说华为和小米现在可以生产电脑了,如下图所示(黄色字体为新增一个产品种类需要做的事),对顶层的工厂接口类也要修改,这是非常麻烦的;

Y 推荐文献
X 参考文献
- 抽象工厂模式(通俗易懂) - CSDN 【推荐】
- 抽象工厂模式 - 菜鸟教程 【不推荐】
内容完全错误(尤其是代码实现),容易误导。
 
    
    本文作者:
        千千寰宇
    
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号