zoukankan      html  css  js  c++  java
  • java23种设计模式——三、工厂模式

    源码在我的githubgitee中获取

    目录

    java23种设计模式—— 一、设计模式介绍
    java23种设计模式—— 二、单例模式
    java23种设计模式——三、工厂模式
    java23种设计模式——四、原型模式
    java23种设计模式——五、建造者模式
    java23种设计模式——六、适配器模式
    java23种设计模式——七、桥接模式
    java23种设计模式——八、组合模式

    工厂模式

    工厂模式介绍

    工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。(百度百科)
    工厂模式又分为:

    • 简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑。
    • 工厂方法模式: 允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定的
    • 抽象方法模式: 抽象工厂是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口。该模式能够提供其他工厂的对象,在其内部创建其他对象。

    简单工厂模式

    属于创建型模式,又叫做静态工厂方法模式,不属于23种GOF设计模式之一。是由一个工厂对象决定创建出哪一种产品类的实例。违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂。

    假设现在有一家餐馆

    public interface Restaurant {
       public void cook();
    }
    

    餐馆有两种菜品:红烧肉和鸡蛋羹

    //鸡蛋羹
    public class Egg implements Restaurant {
        @Override
        public void cook() {
            System.out.println("鸡蛋羹做好了");
        }
    }
    
    //红烧肉
    public class Meet implements Restaurant{
        @Override
        public void cook() {
            System.out.println("红烧肉做好了");
        }
    }
    

    餐馆里有服务员,来负责向后厨传达客人的需求

    public class Waiter {
    	//同样可以定义常量然后通过switch语句来实现
        public static Restaurant getFood(String orderType) {
            Restaurant restaurant = null;
            if(orderType.equals("红烧肉")){
                restaurant = new Meet();
            }else if (orderType.equals("鸡蛋羹")){
                restaurant = new Egg();
            }
            return restaurant;
        }
    }
    

    现在顾客来了,要点一份红烧肉,就只需要和服务员说就行

    public class Customer {
        public static void main(String[] args) {
            Restaurant restaurant = Waiter.getFood("红烧肉");
            restaurant.cook();
        }
    }
    

    输出

    红烧肉做好了
    

    通过以上方法,的确实现了 提供创建实例的功能,而无需关心具体实现。但是我们不难发现,这种方法的扩展性很差,如果餐馆新出了一款菜品,还需要我们在服务员方法里修改。这使得当餐馆的菜品很多时,工厂方法代码逻辑将会非常复杂

    工厂方法模式

    工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。是在工厂模式家族中是用的最多模式,一般项目中存在最多的就是这个模式。是对简单工厂模式的一个优化,让每个对象都有一个与之对应的工厂。

    这里我们接着用上面的例子,假设这家餐厅的生意非常好,所以餐馆的老板把餐馆所有负责点餐的服务员都辞退了,取而代之的是添加了一个收银台,然后让每个厨师只负责做一样菜。这样客人只需要和收银台说要求就行了。

    这里我们接着用上面的类。除去服务员Waiter类

    新建Cashier接口

    /**
     * @author codermy
     * @createTime 2020/6/15
     */
    public interface Cashier {
        public Restaurant getFood();
    }
    

    然后给每一个菜品新建一个工厂类

    EggCooker

    /**
     * @author codermy
     * @createTime 2020/6/15
     */
    public class EggCooker implements Cashier {
        @Override
        public Restaurant getFood() {
            return new Egg();
        }
    }
    

    MeetCooker

    /**
     * @author codermy
     * @createTime 2020/6/15
     */
    public class MeetCooker implements Cashier{
        @Override
        public Restaurant getFood() {
            return new Meet();
        }
    }
    

    然后顾客点单只需要在收银台,餐厅的系统会自动将信息传递给相应的厨师,对应的厨师就能在餐馆中把菜做好

    /**
     * @author codermy
     * @createTime 2020/6/15
     * 消费者
     */
    public class Customer {
        public static void main(String[] args) {
            Cashier order = new EggCooker();
            Restaurant food = order.getFood();
            food.cook();
        }
    }
    

    输出结果

    鸡蛋羹做好了
    

    工厂方法模式解决了简单工厂模式不符合的开闭原则,当添加一个菜品时,只需要再雇佣一个厨师就行(从现实角度看,老板有点亏哦)。但是这也增加了系统的复杂度(菜越多,厨师就越多,这哪家餐馆顶的住)

    抽象工厂模式

    这个模式解决了每个工厂只能创建一类产品(工厂方法模式)的问题

    这里用餐馆的例子不太形象,不是很容易理解,强行举例可能会和上面的方法弄混,我自己绕了好一会,所以我们换一个例子。

    现在我们人手不离手机,我们假设手机有如下几个功能

    //手机产品接口
    public interface IphoneProduct {
        void callup();//打电话
        void sendSms();//发短信
    }
    

    每个人家里又都有路由器,路由器有如下功能

    //路由器产品接口
    public interface IRouterProduct {
        void openwifi();//开启wifi
        void setting();//设置wifi
    }
    

    然后现在有一个抽象产品工厂,是来生产这两样产品的,假设生产手机和路由器的方法是一样的,只是需要加上厂商信息

    //抽象产品工厂
    public interface IProductFactory {
        //生产手机
        IphoneProduct iphoneProduct();
        //生产路由器
        IRouterProduct iRouterProduct();
    }
    

    现在有两家厂商,小米和华为工厂,可以生产手机和路由器,他们两家厂商分别由两条产业线来做手机和路由器

    //小米手机
    public class XiaomiPhone implements IphoneProduct{
    
        @Override
        public void callup() {
            System.out.println("用小米手机打电话");
        }
    
        @Override
        public void sendSms() {
            System.out.println("用小米手机发短信");
        }
    }
    
    
    //小米路由器
    public class XiaomiRouter implements IRouterProduct {
    
        @Override
        public void openwifi() {
            System.out.println("打开小米wifi");
        }
    
        @Override
        public void setting() {
            System.out.println("设置小米wifi");
        }
    }
    
    
    //小米厂商
    public class XiaomiFactory implements IProductFactory {
        @Override
        public IphoneProduct iphoneProduct() {
            return new XiaomiPhone();
        }
    
        @Override
        public IRouterProduct iRouterProduct() {
            return new XiaomiRouter();
        }
    }
    
    
    //华为手机
    public class HuaweiPhone implements IphoneProduct {
    
        @Override
        public void callup() {
            System.out.println("用华为手机打电话");
        }
    
        @Override
        public void sendSms() {
            System.out.println("用华为手机发短信");
        }
    }
    
    //华为路由器
        public class HuaweiRouter implements IRouterProduct {
    
            @Override
            public void openwifi() {
                System.out.println("打开华为wifi");
            }
    
            @Override
            public void setting() {
                System.out.println("设置华为wifi");
            }
        }
    
    //华为工厂
    public class HuaweiFactory implements IProductFactory {
        @Override
        public IphoneProduct iphoneProduct() {
            return new HuaweiPhone();
        }
    
        @Override
        public IRouterProduct iRouterProduct() {
            return new HuaweiRouter();
        }
    }
    

    消费者类

    //消费者/测试类
    public class Customer {
        public static void main(String[] args) {
    
            System.out.println("==============小米产品=================");
            XiaomiFactory xiaomiFactory = new XiaomiFactory();//新建一个小米工厂
            IphoneProduct xiaomiiphoneProduct = xiaomiFactory.iphoneProduct();//小米工厂开始生产小米手机
            xiaomiiphoneProduct.callup();//测试小米手机打电话功能
            IRouterProduct xiaomiiRouterProduct = xiaomiFactory.iRouterProduct();//小米工厂开始生产小米路由器
            xiaomiiRouterProduct.openwifi();//测试小米路由器打开wifi功能
    
            System.out.println("==============华为产品=================");
            HuaweiFactory huaweiFactory = new HuaweiFactory();
    
            IphoneProduct huaweiiphoneProduct1 = huaweiFactory.iphoneProduct();
            huaweiiphoneProduct1.callup();
            IRouterProduct huaweiiRouterProduct = huaweiFactory.iRouterProduct();
            huaweiiRouterProduct.openwifi();
        }
    }
    

    输出

    ==============小米产品=================
    用小米手机打电话
    打开小米wifi
    ==============华为产品=================
    用华为手机打电话
    打开华为wifi
    

    抽象工厂模式相较于以上两种模式难以理解一些。这里提供另一种写法比较好理解,来自Guide哥的博客(以下所有内容)

    不知道大家玩过穿越火线或者吃鸡这类游戏了吗,游戏中存在各种枪。我们假设现在存在AK、M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺便生产AK使用的子弹,生产M4A1的工厂可以顺便生产M4A1使用的子弹。(AK工厂生产AK系列产品包括子弹啊,AK枪的类型啊这些,M4A1工厂同理)
    ————————————————

    (1)创建相关接口:

    public interface Gun {
        public void shooting();
    }
    

    子弹

    public interface Bullet {
        public void load();
    }
    

    (2)创建接口对应实现类:

    AK类

    public class AK implements Gun{
    
        @Override
        public void shooting() {
            System.out.println("shooting with AK");
    
        }
    
    }
    
    

    M4A1类

    public class M4A1 implements Gun {
    
        @Override
        public void shooting() {
            System.out.println("shooting with M4A1");
    
        }
    
    }
    
    

    AK子弹类

    public class AK_Bullet implements Bullet {
    
        @Override
        public void load() {
            System.out.println("Load bullets with AK");
        }
    
    }
    
    

    M4A1子弹类

    public class M4A1_Bullet implements Bullet {
    
        @Override
        public void load() {
            System.out.println("Load bullets with M4A1");
        }
    
    }
    
    

    (3)创建工厂接口

    public interface Factory {
        public Gun produceGun();
        public Bullet produceBullet();
    }
    
    
    

    (4)创建具体工厂

    生产AK和AK子弹的工厂

    public class AK_Factory implements Factory{
    
        @Override
        public Gun produceGun() {
            return new AK();
        }
    
        @Override
        public Bullet produceBullet() {
            return new AK_Bullet();
        }
    
    }
    
    
    

    生产M4A1和M4A1子弹的工厂

    public class M4A1_Factory implements Factory{
    
        @Override
        public Gun produceGun() {
            return new M4A1();
        }
    
        @Override
        public Bullet produceBullet() {
            return new M4A1_Bullet();
        }
    
    }
    
    
    

    (5)测试

    public class Test {
    
        public static void main(String[] args) {  
    
         Factory factory;
         Gun gun;
         Bullet bullet;
    
         factory =new AK_Factory();
         bullet=factory.produceBullet();
         bullet.load();
         gun=factory.produceGun();
         gun.shooting(); 
    
        }
    
    }
    
    

    输出结果:

    Load bullets with AK
    shooting with AK
    
  • 相关阅读:
    86. Partition List
    328. Odd Even Linked List
    19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)
    24. Swap Nodes in Pairs
    2. Add Two Numbers(2个链表相加)
    92. Reverse Linked List II(链表部分反转)
    109. Convert Sorted List to Binary Search Tree
    138. Copy List with Random Pointer
    为Unity的新版ugui的Prefab生成预览图
    ArcEngine生成矩形缓冲区
  • 原文地址:https://www.cnblogs.com/codermy/p/13569486.html
Copyright © 2011-2022 走看看