面试知识点九:设计模式

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与模式》之工厂方法模式

posted @ 2019-07-12 11:10  吹灭读书灯  阅读(425)  评论(0编辑  收藏  举报