设计模式01_设计模式概述、创建型模式概述、单例模式、工厂模式、构建者模式

①. 什么是设计模式

  • ①.在1994年,由ErichGamma、RichardHelm、RalphJohnson和JohnVlissides四人合著出版了一本名为DesignPatterns-ElementsofReusableObject-OrientedSoftware(中文译名:设计模式-可复用的面向对象软件元素)的书,该书首次提到了软件开发中设计模式的概念

  • ②. 对接口编程而不是对实现编程

  • ③. 优先使用对象组合而不是继承

②. 设计模式总览

  • ①. 设计模式是一种思想,灵活运用思想远大于死记代码、咬文爵字

  • ②. 设计模式总览:创建型模式、行为型模式、结构型模式

在这里插入图片描述

  • ③. 组件的生命周期

在这里插入图片描述

③. 设计的7大原则

  • ①. 开闭原则:扩展新类而不是修改旧类
    (软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modification))

  • ②. 里氏替换原则:继承父类而不去改变父类
    (继承必须确保超类所拥有的性质在子类中仍然成立(Inheritance should ensure that any property proved about supertype objects also holds for subtype objects))

  • ③. 依赖倒置原则:面向接口编程,而不是面向实现类
    (高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象(High level modules shouldnot depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details. Details should depend upon abstractions))

  • ④. 单一职责原则:每个类只负责自己的事情,而不是变成万能
    (一个类对另一个类的依赖应该建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface))

  • ⑤. 接口隔离原则:各个类建立自己的专用接口,而不是建立万能接口
    (一个类对另一个类的依赖应该建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface))

  • ⑥. 迪米特法则:无需直接交互的两个类,如果需要交互,使用中间者
    (过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低)
    (只与你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers))

  • ⑦. 合成复用原则:优先组合,其次继承(A、B接口,A1、B1是A、B两个接口的实现类)
    (如果A1类中想要用B1的功能,组合的意思是,将B接口引入A1中,继承的意思是直接A1类继承B1类)
    (又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP)
    软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现)

④. 创建型模式 - 概述

  • ①. 单例Singleton模式、工厂方法FactoryMethod模式、抽象工厂AbstractFactory模式、建造者Builder模式、原型Prototype模式

  • ②. 创建型模式关注点“怎样创建出对象?” 将对象的创建与使用分离

  • ③. 降低系统的耦合度

  • ④. 使用者无需关注对象的创建细节

  1. 对象的创建由相关的工厂来完成各种工厂模式,关注结果
  2. 对象的创建由一个建造者来完成建造者模式,关注过程
  3. 对象始终在系统中只有一个实例单例模式
  4. 对象的创建由原来对象克隆完成(原型模式

⑤. 原型模式 - Prototype

  • ①. 原型模式Prototype Pattern是用于创建重复的对象,同时又能保证性能。
    本体给外部提供一个克隆体进行使用

在这里插入图片描述

  • ②. 代码展示
/**
 * 当前对象是可克隆的
 */
public class User implements Cloneable {

    private String username;
    private Integer age;

    public User(){
        // System.out.println("User对象创建");
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }


    /**
     * 再创建一个人,赋予我的所有属性
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = new User();
        user.setUsername(username);
        user.setAge(age);
        return user;
    }
}
public class GuiguMybatis {

    //缓存user.序列化和反序列化-深克隆
    private Map<String,User> userCache = new HashMap<>();

    /**
     * 从数据库查数据
     * @return
     */
    public User getUser(String username) throws Exception {
        User user = null;
        //缓存中没有
        if(!userCache.containsKey(username)){
            //查询数据库
            user = getUserFromDb(username);
        }else {
            //从缓存中直接拿,脏缓存问题
            //原型已经拿到,但是不能直接给。本人
            user = userCache.get(username);
            System.out.println("从缓存中拿到的是:"+user);
            //从这个对象快速得到一个克隆体克隆人==原型模式
            user = (User) user.clone();
        }

        return user;
    }

    private User getUserFromDb(String username) throws Exception{
        System.out.println("从数据库查到:"+username);
        User user = new User();
        user.setUsername(username);
        user.setAge(18);
        //给缓存中放一个clone
        userCache.put(username, (User) user.clone());
        return user;
    }
}
public class MainTest {
    public static void main(String[] args) throws Exception {
        /**
         从数据库查到:zhangsan
         zhangsan = User{username='zhangsan', age=18}
         从缓存中拿到的是:User{username='zhangsan', age=18}
         zhangsan2 = User{username='zhangsan', age=18}
         从缓存中拿到的是:User{username='zhangsan', age=18}
         zhangsan3 = User{username='zhangsan', age=18}
         false
         */
        GuiguMybatis guiguMybatis = new GuiguMybatis();
        User zhangsan = guiguMybatis.getUser("zhangsan");
        System.out.println("zhangsan = " + zhangsan);
        zhangsan.setUsername("lisi");
        User zhangsan2 = guiguMybatis.getUser("zhangsan");
        System.out.println("zhangsan2 = " + zhangsan2);
        User zhangsan3 = guiguMybatis.getUser("zhangsan");
        System.out.println("zhangsan3 = " + zhangsan3);
        System.out.println(zhangsan2 == zhangsan3);
    }
}
  • ③. 什么场景用到
  1. 性能和安全要求
  2. 一个对象多个修改者的场景。
  3. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时可以考虑使用原型模式拷贝多个对象供调用者使用

⑥. 单例模式 - Singleton

  • ①. 一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。使用volatile禁止指令重排

  • ②. 单例特点:

  1. 某个类只能有一个实例构造器私有
  2. 它必须自行创建这个实例自己编写实例化逻辑
  3. 它必须自行向整个系统提供这个实例对外提供实例化方法

在这里插入图片描述

  • ③. 代码展示
public class Person {
    //懒汉、饿汉
    private volatile static Person instance; //饿汉

    //构造器私有,外部不能实例化
    private Person() {
        System.out.println("创建了Person");
    }


    //提供给外部的方法
    //1、public static synchronized Person guiguBoss() 锁太大
    //2、双重检查锁+内存可见性设计模式
    public static Person getPersonInstance() {
        //如果没有再去创建
        if (instance == null) {
            synchronized (Person.class) {
                if(instance == null){
                    Person person = new Person();
                    //多线程问题
                    instance = person;
                }
            }
        }
        return instance;
    }
}
public class MainTest {
    public static void main(String[] args) {
        Person person1 = Person.getPersonInstance();
        Person person2 = Person.getPersonInstance();
        // true
        System.out.println(person1 == person2);
    }
}
  • ④. 单例使用应用场景
  1. 多线程中的线程池
  2. 数据库的连接池
  3. 系统环境信息(System.getEnv();System.getProperties())
  4. 上下文ServletContext
    public static Properties getProperties() {
        @SuppressWarnings("removal")
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            sm.checkPropertiesAccess();
        }

        return props;
    }
    public static java.util.Map<String,String> getenv() {
	    @SuppressWarnings("removal")
	    SecurityManager sm = getSecurityManager();
	    if (sm != null) {
	        sm.checkPermission(new RuntimePermission("getenv.*"));
	    }
    return ProcessEnvironment.getenv();
    }
   Properties properties = System.getProperties();
   System.out.println(properties);

   //获取当前系统的环境变量
   Map<String, String> getenv = System.getenv();
   System.out.println(getenv);
  • ⑤. 面试问题(等学完SPRING源码再来回顾这里的问题)
  1. 系统环境信息System.getProperties()?
  2. Spring中怎么保持组件单例的?
  3. ServletContext是什么封装Servlet的信息?是单例吗?怎么保证?
  4. ApplicationContext是什么?是单例吗?怎么保证?
    ApplicationContext: tomcat:一个应用部署的一个war包会有一个应用上下文
    ApplicationContext: Spring:表示整个IOC容器怎么保证单例的。ioc容器中有很多组件怎么保证单例
  5. 数据库连接池一般怎么创建出来的,怎么保证单实例?

⑦. 工厂模式Factory - 简单工厂

  • ①. 工厂模式Factory Pattern提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可。难点:写好我们的工厂
  1. 简单工厂(Simple Factory )静态工厂
  2. 工厂方法(Factory Method)多态工厂
  3. 抽象工厂(Abstract Factory)

在这里插入图片描述

  • ②. 简单工厂模式 - Simple Factory
  1. Factory:工厂角色, WuLinFactory
  2. Product:抽象产品角色,Car
  3. ConcreteProduct:具体产品角色, VanCar、MiniCar
  4. 缺点:违背开闭,扩展不易

在这里插入图片描述

  • ③. 案例代码
/**
 * 工厂的产品
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}
public class MiniCar extends AbstractCar{

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar{
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}
/**
 * 简单工厂
 * 1、产品数量极少
 */
public class WuLinSimpleFactory {

    /**
     *
     * @param type  Class: 好像具有扩展性,但是没有解决实际问题
     * @return
     */
    public AbstractCar newCar(String type){

        //核心方法:一切从简
        if("van".equals(type)){
            // 钣金、喷漆、放发动机、申请环保

            return new VanCar();
        }else if("mini".equals(type)){
            return new MiniCar();
        }

        //.....

        //更多的产品,违反开闭原则。应该直接扩展出一个类来造
        return null;
    }
}
public class MainTest {
    public static void main(String[] args) {
        WuLinSimpleFactory factory = new WuLinSimpleFactory();
        AbstractCar van = factory.newCar("van");
        AbstractCar mini = factory.newCar("mini");
        AbstractCar zz = factory.newCar("zz");
        van.run();
        mini.run();
    }
}

⑧. 工厂模式Factory - 工厂方法

  • ①. 四个角色
  1. Product:抽象产品
  2. ConcreteProduct:具体产品
  3. Factory:抽象工厂
  4. ConcreteFactory:具体工厂

在这里插入图片描述

  • ②. 工厂方法的缺点:系统复杂度增加,产品单一

  • ③. 案例展示

/**
 * 工厂的产品
 *
 * 怎么把一个功能提升一个层次:定义抽象抽象类,接口
 * 抽象类,接口  就会有多实现,多实现自然就有多功能
 */
public abstract class AbstractCar {
    String engine;
    public abstract void run();
}
public class MiniCar extends AbstractCar {

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }
    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}
public class RacingCar extends AbstractCar{

    public RacingCar(){
        this.engine = "v8发动机";
    }
    @Override
    public void run() {
        System.out.println(engine+"=--嗖.....");
    }
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar {
    public VanCar(){
        this.engine = "单杠柴油机";
    }
    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}
/**
 * 抽象工厂的层级
 */
public abstract class AbstractCarFactory {
    public abstract AbstractCar newCar();
    //我能造口罩.....
}
/**
 * minicar分厂
 */
public class WulinMinCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}
/**
 * RacingCar分厂
 */
public class WulinRacingCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new RacingCar();
    }
}
public class WulinVanCarFactory extends AbstractCarFactory {
    @Override
    public AbstractCar newCar() {
        return new VanCar();
    }
}
public class MainTest {
    public static void main(String[] args) {
        /**
         v8发动机=--嗖.....
         单杠柴油机--》嗒嗒嗒....
         */
        AbstractCarFactory carFactory = new WulinRacingCarFactory();
        AbstractCar abstractCar = carFactory.newCar();
        abstractCar.run();
        carFactory = new WulinVanCarFactory();
        AbstractCar abstractCar1 = carFactory.newCar();
        abstractCar1. run();
    }
}

⑨. 工厂模式Factory - 抽象工厂

  • ①. 抽象工厂模式图解:
    在这里插入图片描述
  • ②. 抽象工厂模式案例
/**
 * 工厂的产品
 *
 * 怎么把一个功能提升一个层次:定义抽象抽象类,接口
 * 抽象类,接口  就会有多实现,多实现自然就有多功能
 */
public abstract class AbstractCar {
    String engine;
    public abstract void run();
}
public class RacingCar extends AbstractCar {

    public RacingCar(){
        this.engine = "v8发动机";
    }
    @Override
    public void run() {
        System.out.println(engine+"=--嗖.....");
    }
}
/**
 * 具体产品
 */
public class VanCar extends AbstractCar {
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}
/**
 * wulin 汽车集团
 */
public  abstract  class WulinCarFactory extends WulinFactory{
    @Override
    abstract  AbstractCar newCar();

    @Override
    AbstractMask newMask() {
        return null;
    }
}
/**
 * 抽象产品
 */
public abstract class AbstractMask {

    Integer price;
    public abstract void protectedMe();
}
public class CommonMask  extends AbstractMask{
    public CommonMask(){
        price = 1;
    }
    @Override
    public void protectedMe() {
        System.out.println("普通口罩....简单保护...请及时更换");
    }
}
/**
 * 具体产品
 */
public class N95Mask  extends AbstractMask{
    public N95Mask(){
        this.price = 2;
    }

    @Override
    public void protectedMe() {
        System.out.println("N95口罩....超级防护");
    }
}
/**
 * 总厂规范:
 * Wulin集团
 *
 * 使用接口;
 */
public abstract class WulinFactory {
    abstract AbstractCar newCar();
    abstract AbstractMask newMask();
}
/**
 * wulin 汽车集团
 */
public  abstract  class WulinCarFactory extends WulinFactory{
    @Override
    abstract  AbstractCar newCar();

    @Override
    AbstractMask newMask() {
        return null;
    }
}
/**
 * wulin口罩集团
 */
public abstract class WulinMaskFactory extends WulinFactory{
    @Override
    AbstractCar newCar() {
        return null;
    }


    abstract AbstractMask newMask();
}

/**
 * 只造口罩
 */
public class WulinHangZhouMaskFactory extends WulinMaskFactory {

    @Override
    AbstractMask newMask() {
        return new CommonMask();
    }
}
/**
 * 分厂:否则口罩
 */
public class WulinWuHanMaskFactory  extends WulinMaskFactory{

    @Override
    AbstractMask newMask() {
        return new N95Mask();
    }
}
/**
 * 分厂:VanCar
 */
public class WulinVanCarFactory extends WulinCarFactory{
    @Override
    AbstractCar newCar() {
        return new VanCar();
    }

}
public class MainTest {

    public static void main(String[] args) {
        /**
         N95口罩....超级防护
         普通口罩....简单保护...请及时更换
         */
        WulinFactory wulinFactory = new WulinWuHanMaskFactory();
        AbstractMask abstractMask = wulinFactory.newMask();
        abstractMask.protectedMe();

        wulinFactory = new WulinHangZhouMaskFactory();
        AbstractMask abstractMask1 = wulinFactory.newMask();
        abstractMask1.protectedMe();
    }
}

⑩. 建造者模式 - Builder

  • ①. 建造者模式
  1. 产品角色Product:Phone
  2. 抽象建造者Builder:AbstracPhoneBuilder
  3. 具体建造者(Concrete Builder:PhoneBuilder
    在这里插入图片描述
  • ②. 案例演示
/**
 * 抽象建造者
 */
public abstract class AbstractBuilder  {

    Phone phone;
    abstract AbstractBuilder customCpu(String cpu);
    abstract AbstractBuilder customMem(String mem);
    abstract AbstractBuilder customDisk(String disk);
    abstract AbstractBuilder customCam(String cam);
    Phone getProduct(){
        return phone;
    }
}
//@Getter
//@Setter
//@NoArgsConstructor
//@AllArgsConstructor
//@Data
@Builder
public class Phone {

    protected String cpu;
    protected String mem;
    protected String disk;
    protected String cam;

    @Override
    public String toString() {
        return "Phone{" +
                "cpu='" + cpu + '\'' +
                ", mem='" + mem + '\'' +
                ", disk='" + disk + '\'' +
                ", cam='" + cam + '\'' +
                '}';
    }

    public String getCpu() {
        return cpu;
    }

    public String getMem() {
        return mem;
    }

    public String getDisk() {
        return disk;
    }

    public String getCam() {
        return cam;
    }
}
public class XiaomiBuilder  extends AbstractBuilder{
    public XiaomiBuilder(){
//        phone =
//                new Phone();
        phone = Phone.builder().build();
    }

    /**
     *
     * @param cpu
     */
    @Override
    AbstractBuilder customCpu(String cpu) {
        phone.cpu = cpu;
        return this;
    }

    @Override
    AbstractBuilder customMem(String mem) {
        phone.mem = mem;
        return this;
    }

    @Override
    AbstractBuilder customDisk(String disk) {
        phone.disk = disk;
        return this;
    }

    @Override
    AbstractBuilder customCam(String cam) {
        phone.cam = cam;
        return this;
    }
}
public class MainTest {
    public static void main(String[] args) {
        AbstractBuilder builder = new XiaomiBuilder();
        //建造这个手机
//        builder.customMem("16G");
//        builder.customDisk("1T");
//        builder.customCam("2亿");
//        builder.customCpu("骁龙8个8");
        //链式建造者 Swagger
        Phone phone = builder.customCpu("骁龙8个8")
                .customCam("2亿")
                .customDisk("1T")
                .customMem("16G")
                .getProduct();
        System.out.println(phone);
        Phone build = Phone.builder()
                .cpu("1")
                .mem("2")
                .cam("3")
                .disk("4")
                .build();
        System.out.println(build);
    }
}
  • ③. 什么场景用到?
  1. StringBuilder:append();给谁append呢?
  2. Swagger-ApiBuilder:
  3. 快速实现。Lombok-Builder模式
  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

所得皆惊喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值