zoukankan      html  css  js  c++  java
  • 面试知识点九:设计模式

    88.说一下你熟悉的设计模式?

    89.简单工厂和抽象工厂有什么区别?

    88.说一下你熟悉的设计模式?

      参考:设计模式总结

      1、单例模式:单例模式保证一个类仅有一个实例,同时这个类还必须提供一个访问该类的全局访问点。作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个(当然也可以不存在)。

      单例模式的结构图

    image

    从上面的类图中可以看出,在单例类中有一个构造函数 Singleton ,但是这个构造函数却是私有的(前面是“ - ”符号),然后在里面还公开了一个 GetInstance()方法。

    根据上述描述,可以得到如下代码:

    public class Singleton {
    
        private static Singleton instance;
        /*
        * 构造函数私有,不能通过其创建对象
        * */
        private Singleton(){
    
        }
        
        /*
        * 提供一个获取对象的公共方法
        * */
        public static Singleton getInstance(){
            if(instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    
    }

    测试一下:

    public class Test {
        public static void main(String[] args) {
            Singleton instance1 = Singleton.getInstance();
            Singleton instance2 = Singleton.getInstance();
            System.out.println(instance1 == instance2);
    
        }
    }

    结果:

    true

    可以看到,获取的是同一个实例。

    完善一下,多线程情况下实现单例模式。先模拟一下上述代码中多线程下的问题:

    public class Singleton {
    
        private static Singleton instance;
        
        private Singleton(){
    
        }
        
        public static Singleton getInstance(){
            if(instance == null){
                try {
                    Thread.sleep(10);
                    instance = new Singleton();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return instance;
        }
    }
    public class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println(Singleton.getInstance().hashCode());
        }
    }

    测试一下:

    public class Test {
        public static void main(String[] args) {
            Thread[] threads = new Thread[5];
            for (int i = 0; i < threads.length; i++) {
                threads[i] = new Thread01();
            }
    
            for (int i = 0; i < threads.length; i++) {
                threads[i].start();
            }
    
        }
    }

    结果:

    2057546272
    1311791352
    1892782834
    528123358
    1996397762

    可以看到,上述代码在多线程模式下单例模式存在问题,返回的可能不再是同一个实例对象。解决方法,if条件判断加锁

    public class Singleton {
    
        private static Singleton instance;
        private static Object synchObject = new Object();
    
        private Singleton(){
    
        }
    
        public static Singleton getInstance(){
            synchronized (synchObject){
                if(instance == null){
                    instance = new Singleton();
                }
            }
            return instance;
        }
    }

    其他不变,测试结果:

    156522743
    156522743
    156522743
    156522743
    156522743

    单例模式多线程下获取的也是同一个对象。例子中的是懒汉式单例模式,还有饿汉式单例模式。

    单例模式(Singleton)

    89.简单工厂和抽象工厂有什么区别?  

    简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现,但不属于23种GOF设计模式之一。
    类比:导演就会说下一场戏,范·迪塞尔下一场戏需要开跑车(参数),要去参加五环首届跑车拉力赛,这时候场务(工厂类)接到导演的命令(跑车参数)后需要从车库开出一辆跑车(具体产品)交到范·迪塞尔手上让他去准备跑车拉力赛。这套程序的整个生命周期就算完成了。

     代码演示:

    定义一个Car接口:

    public interface Car {
        void getCar();
    }

    定义三个实现类:

    public class SportCar implements Car {
        @Override
        public void getCar() {
            System.out.println("获得跑车");
        }
    }
    public class JeepCar implements Car {
        @Override
        public void getCar() {
            System.out.println("获得越野车");
        }
    }
    public class AudiCar implements Car {
        @Override
        public void getCar() {
            System.out.println("获得奥迪车");
        }
    }

    定义工厂:

    public class CarFactory {
        public Car getCar(String carType) throws Exception {
            switch (carType){
                case CarType.sportCarType:
                    return new SportCar();
                case CarType.jeepCarType:
                    return new JeepCar();
                case CarType.audiCarType:
                    return new AudiCar();
                default:
                    throw new Exception("无车可用");
            }
        }
    }

    对应的CarType变量:

    public class CarType {
        public static final String sportCarType = "0";
        public static final String jeepCarType = "1";
        public static final String audiCarType = "2";
    }

    测试一下:

    public class Test {
        public static void main(String[] args){
            try {
                CarFactory carFactory = new CarFactory();
                Car car = carFactory.getCar(CarType.audiCarType);
                car.getCar();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    结果:

    获得奥迪车

    总结一下简单工厂模式的优缺点:

    • 优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
    • 缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则

    接下来看抽象工厂,参考《JAVA与模式》之抽象工厂模式

    抽象工厂模式的优点

    • 分离接口和实现

      客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。

    • 使切换产品族变得容易

      因为一个具体的工厂实现代表的是一个产品族,比如上面例子的从Intel系列到AMD系列只需要切换一下具体工厂。

    抽象工厂模式的缺点

    • 不太容易扩展新的产品

      如果需要给整个产品族添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。

    最后总结一下简单工厂与抽象工厂的区别:

      【设计模式】简单工厂、工厂方法与抽象工厂的区别

    参考资料:详解设计模式六大原则

         详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂)

         《JAVA与模式》之简单工厂模式

         《JAVA与模式》之工厂方法模式

  • 相关阅读:
    redis 学习导航
    springcloud用法
    springcloud-概念
    倒排索引思想
    Java多线程编程实战读书笔记(一)
    java多线程中的三种特性
    汇编语言笔记
    同步/异步和阻塞/非阻塞
    乐观锁和悲观锁
    双亲委派模型
  • 原文地址:https://www.cnblogs.com/zfyang2429/p/11174924.html
Copyright © 2011-2022 走看看