• 设计模式之工厂模式(简单工厂,工厂方法,抽象工厂)


    前语:在工厂模式中常常会分不清楚(简单工厂和工厂方法,抽象工厂)三者之前的区别,在学习设计模式时也容易混淆,这里对三者进行学习;

    工厂模式:顾名思义,客户希望通过工厂(一个或一系列方法)去生产(一个或者一系列产品的实例)

    本质:工厂模式是创建者模式,创建对象实例;

    一.简单工厂

      简单工厂类(SimpleFactory)通过接受参数的形式,调用getShape()方法区得到想要创建的对象;

          如图所示:

     优点:简单而且粗暴的创建对象,通过参数可以创建任何实现了接口的对象

     缺点:(1)当对象类过多,简单工厂就会很臃肿,不利于简单工厂的维护 (2)不符合开放封闭原则,每次增加一个产品子类,就需要修改简单工厂

     简单写了一下实现代码:但是不是按照上述UML关系图

    产品接口Food的代码如下

    public interface Food {
        void eat();
    }

    实现产品接口的类Apple.class

    public class Apple implements   Food {
        @Override
        public void eat() {
            System.out.println("当前吃是苹果");
        }
    }
    

    实现产品接口的类Pear.class

    public class Pear implements Food {
        @Override
        public void eat() {
            System.out.println("当前正在吃梨子");
        }
    }
    

    实现产品接口的类Banana.class

    public class Banana implements Food{
        @Override
        public void eat() {
            System.out.println("当前正在吃香蕉");
        }
    }
    

    简单工厂方法SimpleFactory.class

    public class SimpleFactory {
    
        private Food food=null;
    
        public Food getFood(String FoodName){
            if(FoodName=="" || FoodName==null){
                return null;
            }
    
            switch (FoodName){
                case "Banana": food =new Banana();break;
                case "Apple" : food =new Apple(); break;
                case "Pear"  : food =new Pear();break;
                default: food=null;break;
            }
            return food;
        }
    }
    

    方法运行Main

    //简单工厂
    //1.对象类型 有多种子类
    //2.工厂只有 一个
    //3.对象的创建延迟到工厂实例中
    public class Main {
    
        public static void main(String[] args) {
            //Client 客户来吃水果
            Food food =null;
    
            SimpleFactory factory =new SimpleFactory();
    
            food=factory.getFood("Pear");
    
            food.eat();
        }
    }
    

    运行结果:

     二.工厂方法

    工厂方法为每一个对象提供一种产品提供一个工厂,用于该类的实例化;

    如下UML所示为工厂方法。

     

    工厂方法的实现过程代码:

    Food接口

    public interface  Food {
         void eat();
    }

    Factory接口

    public interface Factory {
        Food create();
    }
    

    Apple.class类

    public class Apple implements   Food {
        @Override
        public void eat() {
            System.out.println("当前吃是苹果");
        }
    }
    

    Banana.class类

    public class Banana implements Food{
    
        @Override
        public void eat() {
            System.out.println("当前正在吃香蕉");
        }
    }

    与之对应的工厂

    AppleFactory.class

    public class AppleFactory implements  Factory {
        @Override
        public Food create() {
            return new Apple();
        }
    }
    

    BananaFactory.clsss

    public class BananaFactory implements  Factory{
        @Override
        public Food create() {
            return new Banana();
        }
    }

    工厂方法调用

      public static void main(String[] args) {
    
            Food food =null;
    
            Factory factory =null;
    
            /****************/
            String foodName="Apple";
            switch (foodName){
    
                case "Apple":factory =new AppleFactory();break;
                case "Banana":factory =new BananaFactory();break;
                default:factory =null;
            }
            /***************/
    
            food =factory.create();
    
            food.eat();
        }

    在调用方法上仍然扩展性不足,但是可以采取反射技术弥补

    运行结果:

    优点:(1)与简单工厂相比,提高了工厂的扩展性,符合开放封闭原则;

    缺点:(2)实现起来较之于简单工厂复杂,无法生存一系列产品

    三.抽象工厂

    抽象工厂是对于产品系列而言

    比如衣服分为帽子,T恤从种类上分,从品牌的角度分为LiNing,Nike,针对这种情况需要创建一个产品族的对象,可以采取抽象工厂的方法

    以此为思路,创建的抽象工厂UML为:

    具体代码实现

    Hat接口

    //帽子
    public interface Hat {
         void put();
    }
    

    Shirt接口

    //T恤
    public interface Shirt {
        void wear();
    }
    

    Shop接口

    public interface Shop {
    
        Hat SellHat();
    
        Shirt SellShirt();
    
        static Shop setShop(String typeName){
    
            try {
                Class c =Class.forName(typeName);
    
                Shop shop=(Shop) c.newInstance();
    
                return shop;
            }catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
    

    LiNingHat.class帽子类

    public class LiningHat implements   Hat {
        @Override
        public void put() {
            System.out.println("穿上李宁的帽子");
        }
    }
    

    LiNingShirt.clas李宁的T恤

    public class LiningShirt implements Shirt {
    
        @Override
        public void wear() {
            System.out.println("穿上李宁的T桖");
        }
    }
    

    Nike的帽子NikeHat.class

    public class NikeHat implements Hat{
        @Override
        public void put() {
            System.out.println("穿上耐克的帽子");
        }
    }
    

    Nike的T恤NikeShirt.class

    public class NikeShirt implements   Shirt{
        @Override
        public void wear() {
            System.out.println("穿上耐克的T桖");
        }
    }

    李宁的商店LiNingShop.class

    public class LiningShop implements   Shop{
    
        @Override
        public Hat SellHat() {
            return new LiningHat();
        }
    
        @Override
        public Shirt SellShirt() {
            return new LiningShirt();
        }
    }
    

    Nike的商店NikeShop.class

    //Nike商店
    public class NikeShop implements   Shop {
        @Override
        public Hat SellHat() {
            return new NikeHat();
        }
    
        @Override
        public Shirt SellShirt() {
            return new NikeShirt();
        }
    }

    调用抽象工厂的过程

    public static void main(String[] args) {
            Hat hat =null;
            Shirt shirt =null;
    
            Shop shop =Shop.setShop("v3.LiningShop");
    
            hat =shop.SellHat();
            shirt =shop.SellShirt();
    
            hat.put();
            shirt.wear();
        }

    调用结果:

    优点:可以针对一系列对象

    确定:只针对一系列对象

    总结:

    简单工厂:针对同一级别的不同对象(扩展性较差)

    工厂方法:针对同一级别的固定对象(开放修改接口,扩展性好)

    抽象工厂:针对不同系列的全部对象(不支持单个产品扩展,只支持产品族扩展)

    使用总结:(1)工厂模式中,工厂类采取的单例模式

         (2)工厂类的基类可以是接口也可以是抽象类

         (3)调用工厂采取的是指针和引用

  • 相关阅读:
    hashlib加密算法
    gc 模块常用函数
    functools函数中的partial函数及wraps函数
    ctime使用及datetime简单使用
    __new__方法理解
    __getattribute__小例子
    == 和 is 的区别
    线程_可能发生的问题
    线程_进程池
    【网站】 简单通用微信QQ跳转浏览器打开代码
  • 原文地址:https://www.cnblogs.com/ad-zhou/p/11391159.html
Copyright © 2020-2023  润新知