java设计模式 23种设计模式和思想

设计模式

1、概述

​ 设计模式不是一种语法上的规定,而是一种思想,是解决特定场景问题所总结出的一系列方法,可以灵活运用在我们实际开发中,提高我们代码的扩展性,可读性,稳健性,和复用性,从而使我们编写的代码更加稳健和安全

1995年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著(Addison-Wesley,1995)。这几位作者常被称为"四人组(Gang of Four)",而这本书也就被称为"四人组(或 GoF)"书。共收录了23中设计模式,是我们软件设计模式领域的里程碑

就java体系来说,GOF是Java基础知识和j2EE框架架知识之间一座隐性的,我们都是知道抽象类和接口是java的核心思想,而这些设计模式便是转换你抽象的思维,从而提高你抽象的能力,进而灵活运用在代码编辑中。

​ *思想的转变,还是要体现在日常开发中,这样,我们才能 更好的体会这些思想带给我们的便利之处

2、OOP七大原则

2.1、 开闭原则:对扩展开放,对修改关闭

​ 这里所指的就是我们设计模式的核心思想了,这种模式要求我们,在代码设计上,在不修改原代码的情况下,去增加功能,减小耦合性,再就是上面提到的扩展性了,基本上我们所有的设计模式,都是围绕这个思想进行展开的,

2.2、里氏替换原则:继承需保证超类中特性在子类中依然成立

​ 继承有很多的优点,但是也有缺点,采用里氏替换的原则就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。在实际项目中,每个子类对应不同的项目含义,使用父类作为参数,传递不同子类完成不同逻辑,非常完美!我们这个就比较好理解了,比如我们的数组,是线性表结构的表现,是很多数据结构类的超类,所以它的特性,在其他类中也都是存在的,其它类也都具有这个特性

2.3、依赖倒置原则:面向接口编程,而不是面向实现编程

​ 高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象

​ 万物皆对象,只要是对象,那便是由分类的,抽象类的表示是 has a ,接口则是 is a ,但是我们在具体的实现上,大多数情况中,接口可以对有共同特性的类抽离出来,面向抽象编程,而不是面向实现编程,从而减小耦合度

2.4、单一职责:控制类的粒度大小,将对象解耦,从而提高内聚性

​ 在日常开发中,其实就有再做这件事情,我们会把代码进行抽离成不同的类,进而使他们各自具有不同的功能,互不影响,依赖,这样在我们系统后期扩展,改造当中,也会减少大量的工作

2.5、接口隔离原则:为不同的类,建立它们需要的专有接口

​ 不要强迫客户程序依赖于自己不需要的接口方法,一个接口只提供一个额定的功能,不应该把所有操作都封装到一个类中,根据具有共同特性的类,为他们提供专属他们的接口,这样在后期对这类功能做出扩展的时候,遵守接口定义,提高内聚性

2.6、迪米特法则:只与你的朋友交谈,不与 ‘陌生人说话’

​ 一个对象应该和其他对象的关联越少越好,对象关联越多,耦合度就越高,如果类和类之间特定场景下需要关联,则可以通过一个中间类来实现这个功能,而不是将这两个类关联起来,就好像生活中我们的适配器是一样

2.7 、合成复用原则:优先使用组合或聚合关系来实现,其次才考虑继承关系来实现

​ 新的对象通过关联关系,使用一些其他已存在的类对象,将它们各自拥有的功能,变为新对象的一部分,如果使用继承,会破坏系统原有的架构和维护的复杂度,维持类原有的封装性,提高复用的灵活性

3、创建型模式

单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式

3.1、单例模式

1. 保证类实例只有一个
2. 懒汉模式和饿汉模式
package cn.hhw.designModel.factory.single;

/**
 * Author: jyh
 * Date: 2020/8/27 22:31
 * Content:电脑产品类,   保证对象的实例只有一个,减少系统资源的消耗,
 * spring IOC思想 就是运用了这样的设计模式,和原型模式来管理bean实例
 * 		饿汉模式
 * 饿汉,见名直意,就是类一开始就存在
 * 1.构造方法私有化
 * 2.创建静态类实例,在类被加载的时候就创建
 * 3.增加一个静态方法,返回类实例给调用者
 */
public  class Computer {

    private String CPU;
    private String memory;
    private String disk;
    private String monitor;

    private static Computer computer=new Computer();
    //将构造方法私有,通过类内部返回一个类实例对象
    private Computer() {
    }

    public static Computer getInstants(){
        return computer;
    }

}


package cn.hhw.designModel.factory.single;

/**
 * Author: jyh
 * Date: 2020/8/27 22:31
 * Content:电脑产品类,   保证对象的实例只有一个,减少系统资源的消耗,
 * spring IOC思想 就是运用了这样的设计模式,和原型模式来管理bean实例
 * 
 *  懒汉模式    不提前创建类实例,当有调用者需要使用的时候,再创建
 * 1.构造方法私有化
 * 2.将对象实例 加 修饰volatile 保证在多线程下数据可见性的安全性,对象的实例永远只有一个
 * 3.增加一个静态方法,返回类实例给调用者
 * 4.将方法加同步锁,DCL   双重检查,防止多线程下产生的线程安全问题
 */
public  class Computer2 {

    private String CPU;
    private String memory;
    private String disk;
    private String monitor;

    //让对象在多线程中可见性,禁止指令重排序
    private static volatile Computer2 computer;

    //将构造方法私有,通过类内部返回一个类实例对象
    private Computer2() {
    }

    //DCL 双重检查
    public static  Computer2 getInstants(){
        if(computer == null){
            synchronized(Computer2.class) {
                if(computer == null) {
                    return new Computer2();
                }
            }
        }
        return computer;
    }

}

结语:饿汉模式比较简单,没有线程安全问题。但懒汉模式存在线程安全问题,当同一时间多个线程去进入getInstant方法时,可能会创建多个类实例,所以我们需要加锁,而当我们加了synchoronized 同步锁之后,虽然不会再出现这样的问题,但是锁的粗度太大了,以后每个线程进这个方法都要阻塞等待,其实我们只需要保证前几次的线程进入方法时,不出现问题,当类还没完成创建的时候,同时有两个线程进入非空校验,之后有一个线程获得锁,创建出实例,这个时候另外一个线程也拿到锁,但当它拿到锁之后,会再次进行非空判断,发现对象已经被创建过了,便会直接类实例对象,而后面再来的线程根本就不会进入锁,所以用一种巧妙DCL的方式,解决了多线程下的安全问题

3.2、工厂模式

	1、 实现创建者和调用者的分离,用工厂方法代替原有的new

	2、将对象的创建统一管理和控制,从而让调用者和我们的实现类解耦
3.2.1、简单工厂模式
	- 用于生产同一等级结构内的任意产品
package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:定义一个车的接口,用来规范
 */
public interface Car {
    void getCarName();
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:50
 * Content:
 */
public class AodiCar  implements Car{
    @Override
    public void getCarName() {
        System.out.println("五菱宏光");
    }
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:
 */
public class DazhongCar implements Car{

    @Override
    public void getCarName() {
        System.out.println("大众车");
    }
}
package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:54
 * Content:
 * 将对象的创建,交给工厂类来创建,统一管理同一类实例
 * 缺点,当我们需要添加 新的车时,还是需要增加方法,修改原有代码 违背了开闭原则
 */
public class FactoryCar {

    public static  DazhongCar produDazhongCar(){
        return new DazhongCar();
    }
    public static AodiCar produAodiCar(){
        return new AodiCar();
    }
}

package cn.hhw.designModel.factory.simple;

/**
 * Author: jyh
 * Date: 2020/8/27 20:51
 * Content: 消费者
 * 1. 简单工厂模式,可以代替用户直接new对象的方式,而是通过外部的车工厂类去创建不同车的类,但是,当我们要增加新的车时,必须要在车工厂
 *  类里添加方法,修改了原有的类和代码, 这样的方式,违背了我们设计模式的开闭原则,可以扩展,不可以修改
 */
public class Consumer {
    public static void main(String[] args) {
//        Car dazhongCar = new DazhongCar();
//        Car dadoCar = new AodiCar();
//        dazhongCar.getCarName();
//        dadoCar.getCarName();
        Car dazhongCar = FactoryCar.produDazhongCar();
        Car aodiDaCar= FactoryCar.produAodiCar();
        dazhongCar.getCarName();
        aodiDaCar.getCarName();
    }
}

结语: 简单工厂模式,可以代替用户直接new对象的方式,而是通过外部的车工厂类统一去创建不同车的类实例,但是,当我们要增加新的车时,必须要在车工厂
类里添加方法,修改了原有的类和代码, 这样的方式,违背了我们设计模式的开闭原则,可以扩展,不可以修改

3.2.1、工厂方法模式

用来生产同一等级结构中的固定类型产品

/**
 * Author: jyh
 * Date: 2020/8/27 20:48
 * Content:定义一个车的接口,用来规范
 */
public interface Car {
    void getCarName();
}


public class WuLingCar implements Car {
    @Override
    public void getCarName() {
        System.out.println("五菱宏光");
    }
}
public class DazhongCar implements Car {

    @Override
    public void getCarName() {
        System.out.println("大众车");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:02
 * Content: 车工厂接口,用户可以根据不同分类的车,去构建自己的对应车工场
 */
public interface Factory {
        Car CreateCar();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:03
 * Content:大众车厂
 */
public class DazhongFactory implements Factory {
    @Override
    public Car CreateCar() {
        return new DazhongCar();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:20
 * Content:五菱宏光车厂
 */
public class WuLingFactory implements Factory {
    @Override
    public Car CreateCar() {
        return new WuLingCar();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:05
 * Content:用户可以选择不同的车工场,去获得资金想要的车。
 * 1.车工厂接口,2.不同车的工厂实现 3.车的工厂。4.不同车的实现
 * 用户需要什么车,便去获取什么车工厂。这样实现了,在不修改源代码的情况下,动态扩展
 */
public class Consumer {

    public static void main(String[] args) {
        DazhongFactory dazhongFactory = new DazhongFactory();
        Car dazhongcar = dazhongFactory.CreateCar();
        AodiFactory aodiFactory = new AodiFactory();
        Car aodicarCar = aodiFactory.CreateCar();
        dazhongcar.getCarName();
        aodicarCar.getCarName();
        WuLingFactory wuLingFactory = new WuLingFactory();
        Car car = wuLingFactory.CreateCar();
        car.getCarName();

    }
}

结语:我们对车工厂也提取了一个接口,这样实现了再增加新的车的时候,不需要修改原有类,只需要动态的增加对应的车和车工厂即可

符合开闭原则,解决了简单工厂的问题,但实际观察下来,代码复杂度太高了,类一直在增加,简单工厂虽然某种程度上不符合设计原则,但实际使用却是最多的

3.3、抽象工厂模式

围绕一个超级工厂,创建其他工厂,又称为其他工厂的工厂

/**
 * Author: jyh
 * Date: 2020/8/27 21:10
 * Content:手机接口
 */
public interface Phone {
    //开机
    void start();
    //关机
    void shutdown();
    //发短信
    void sedMes();
    //打电话
    void call();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:15
 * Content:路由器接口
 */
public interface Routers {
    //开机
    void start();
    //关机
    void shutdown();
    //开始wifi
    void Wifi();
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:12
 * Content:华为手机
 */
public class HuaWeiPhone implements Phone {
    @Override
    public void start() {
        System.out.println("华为手机开机");
    }

    @Override
    public void shutdown() {
        System.out.println("华为手机关机");
    }

    @Override
    public void sedMes() {
        System.out.println("华为手机发短信");
    }

    @Override
    public void call() {
        System.out.println("华为手机打电话");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:13
 * Content:小米手机
 */
public class XiaoMiPhone implements Phone {
    @Override
    public void start() {
        System.out.println("小米手机开机");

    }

    @Override
    public void shutdown() {
        System.out.println("小米手机关机");

    }

    @Override
    public void sedMes() {
        System.out.println("小米手机发短信");

    }

    @Override
    public void call() {
        System.out.println("小米手机打电话");
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:23
 * Content:华为路由器
 */
public class HuaweiRouter implements Routers {
    @Override
    public void start() {
        System.out.println("华为路由器开机");
    }

    @Override
    public void shutdown() {
        System.out.println("华为路由器关机");

    }

    @Override
    public void Wifi() {
        System.out.println("华为路由器打开wifi");

    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:23
 * Content:小米路由器
 */
public class XiaoMiRouter implements Routers {
    @Override
    public void start() {
        System.out.println("小米路由器开机");
    }

    @Override
    public void shutdown() {
        System.out.println("小米路由器关机");

    }

    @Override
    public void Wifi() {
        System.out.println("小米路由器打开wifi");

    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:24
 * Content: 产品工厂接口,只提供生产产品的定义,具体需要生产哪类产品,需要产品厂家自己增加实现
 */
public interface ProductFatory  {
    Phone gePhone();
    Routers getRouters();

}
/**
 * Author: jyh
 * Date: 2020/8/27 21:29
 * Content: * Content:华为的产品工厂,用来生产华为的产品
 */
public class HuaweiFactory implements ProductFatory {
    @Override
    public Phone gePhone() {
        return new HuaWeiPhone();
    }

    @Override
    public Routers getRouters() {
        return new HuaweiRouter();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:29
 * Content:小米的产品工厂,用来生产小米的产品
 */
public class XiaoMiFactory implements ProductFatory {
    @Override
    public Phone gePhone() {
        return new XiaoMiPhone();
    }

    @Override
    public Routers getRouters() {
        return new XiaoMiRouter();
    }
}
/**
 * Author: jyh
 * Date: 2020/8/27 21:30
 * Content:用户在需要使用哪家产品的时候,只需要创建哪家的厂家即可
 */
public class Consomer {
    public static void main(String[] args) {
        //华为工厂
        HuaweiFactory huaweiFactory = new HuaweiFactory();
        //获得华为手机
        Phone huaweiphone = huaweiFactory.gePhone();
        huaweiphone.start();
        huaweiphone.shutdown();
        huaweiphone.sedMes();
        huaweiphone.call();
        //获得华为路由器
        Routers huaweirouRouters = huaweiFactory.getRouters();
        huaweirouRouters.start();
        huaweirouRouters.shutdown();
        huaweirouRouters.Wifi();
        System.out.println("=====================================================");
        //小米工厂
        XiaoMiFactory xiaomiFactory = new XiaoMiFactory();
        //获得小米手机
        Phone xiaomiphone = xiaomiFactory.gePhone();
        xiaomiphone.start();
        xiaomiphone.shutdown();
        xiaomiphone.sedMes();
        xiaomiphone.call();
        //获得小米路由器
        Routers xiaomirouRouters = xiaomiFactory.getRouters();
        xiaomirouRouters.start();
        xiaomirouRouters.shutdown();
        xiaomirouRouters.Wifi();
    }
}

结语:抽象工厂模式是对应产品工厂接口,只提供生产产品的定义,具体需要生产哪类产品,需要产品厂家自己增加实现,这样的的设计模式,可以扩展出不同的产品族,但不能再增加产品,因为产品接口已经定义好了,比如我们可以增加苹果路由器,苹果手机,和苹果工厂,这样动态扩展即可,不需要修改源代码便可以实现

工厂模式应用场景:

	- JDK的calendar的genInstance方法
	- jdbc的connection对象获取
	- springIOC容器创建管理bean对象
	- 反射中Class对象的newInstance

3.4、建造者模式

3.4.1、指挥者存在内部

​ 提供了一种创建对象的最佳方式,将一个复杂的对象创建与它的表示分析,使得同样的构建过程可以创建不同的表示

/**
 * Author: jyh
 * Date: 2020/8/27 22:55
 * Content:模拟复杂类
 */
public class Product {
    private String executeA;
    private String executeb;
    private String executec;
    private String executed;

    public String getExecuteA() {
        return executeA;
    }

    public void setExecuteA(String executeA) {
        this.executeA = executeA;
    }

    public String getExecuteb() {
        return executeb;
    }

    public void setExecuteb(String executeb) {
        this.executeb = executeb;
    }

    public String getExecutec() {
        return executec;
    }

    public void setExecutec(String executec) {
        this.executec = executec;
    }

    public String getExecuted() {
        return executed;
    }

    public void setExecuted(String executed) {
        this.executed = executed;
    }

    @Override
    public String toString() {
        return "Product{" +
                "executeA='" + executeA + '\'' +
                ", executeb='" + executeb + '\'' +
                ", executec='" + executec + '\'' +
                ", executed='" + executed + '\'' +
                '}';
    }
}
package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 22:57
 * Content: 建造者的接口定义
 */
public abstract  class  Executer {

    //建造步骤1.
    abstract void executeA();
    //建造步骤2.
    abstract void executeB();
    //建造步骤2.
    abstract void executeC();
    //建造步骤3.
    abstract void executeD();
    //建造步骤4.
    abstract Product getProduct();
}

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 22:59
 * Content:实际真实的建造者,可以有多个建造者
 */
public class Worker extends Executer {
    private Product product;

    //此步为关键,实际复杂对象的实例化必须要有建造者完成。最终返回
    public Worker() {
        this.product = new Product();
    }

    //建造步骤1.打地基
    @Override
    void executeA() {
        product.setExecuteA("地基");
        System.out.println("地基");
    }

    //建造步骤2.铺地板
    @Override
    void executeB() {
        product.setExecuteA("地板");
        System.out.println("地板");
    }
    //建造步骤3.装家具
    @Override
    void executeC() {
        product.setExecuteA("装家具");
        System.out.println("装家具");
    }

    //建造步骤3.贴瓷砖
    @Override
    void executeD() {
        product.setExecuteA("贴瓷砖");
        System.out.println("贴瓷砖");
    }

    @Override
    Product getProduct() {
        return product;
    }
}

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 23:10
 * Content:指挥者,指挥建造者构建复杂对象,可以控制建造者建造的过程
 */
public class Leader {

    //传入一个建造者,指挥建造者建造出类,进行返回,此处模拟建房子步骤
    public Product Product(Executer executer){
        executer.executeB();
        executer.executeA();
        executer.executeC();
        executer.executeD();
        return executer.getProduct();
    }
}

package cn.hhw.designModel.factory.builder.demo2;

/**
 * Author: jyh
 * Date: 2020/8/27 23:13
 * Content:调用者,需要一个对象实例
 */
public class Test {
    public static void main(String[] args) {
        //创建指挥者,通过指挥者调用建造者,生产对象
        Leader leader = new Leader();
        Product product = leader.Product(new Worker());
        System.out.println(product);
    }
}

上述事例是Builder常规用法,在用户不知道对象的建造过程和细节的情况下就可以直接完成创建复杂对象,建造和表示分离,实现解耦,创建步骤分解在不同的方法中,使得创建过程更加清晰,具体的建造者类之间是相互独立的,有利于系统扩展,增加新的建造者,也不需要修改原有类库,符合‘开闭原则’

3.4.2、指挥权交给用户
package cn.hhw.designModel.factory.builder.demo3;

/**
 * Author: jyh
 * Date: 2020/8/27 23:15
 * Content:复杂产品类
 */
public class Hamburger {
    private String hanbao = "汉堡";
    private String drink = "饮料";
    private String chip ="薯条";
    private String cheese="奶酪";


    @Override
    public String toString() {
        return "Hamburger{" +
                "hanbao='" + hanbao + '\'' +
                ", drink='" + drink + '\'' +
                ", chip='" + chip + '\'' +
                ", cheese='" + cheese + '\'' +
                '}';
    }

    public String getHanbao() {
        return hanbao;
    }

    public void setHanbao(String hanbao) {
        this.hanbao = hanbao;
    }

    public String getDrink() {
        return drink;
    }

    public void setDrink(String drink) {
        this.drink = drink;
    }

    public String getChip() {
        return chip;
    }

    public void setChip(String chip) {
        this.chip = chip;
    }

    public String getCheese() {
        return cheese;
    }

    public void setCheese(String cheese) {
        this.cheese = cheese;
    }
}

package cn.hhw.designModel.factory.builder.demo3;

import java.util.HashMap;

/**
 * Author: jyh
 * Date: 2020/8/27 23:17
 * Content:建造者接口
 */
public abstract class Person {

    abstract Person executeA(String hanbao);
    abstract Person executeB(String drink);
    abstract Person executeC(String chip);
    abstract Person executeD(String hanbao);
    abstract  Hamburger gethamburger();
}

package cn.hhw.designModel.factory.builder.demo3;

import java.util.HashMap;

/**
 * Author: jyh
 * Date: 2020/8/27 23:19
 * Content:实际建造者
 */
public class Waiter extends Person{
    private Hamburger hanHamburger;


    public Waiter(){
        hanHamburger=new Hamburger();
    }

    @Override
    Waiter executeA(String hanbao) {
        hanHamburger.setHanbao(hanbao);
        System.out.println(hanbao);
        return this;
    }

    @Override
    Waiter executeB(String drink) {
        hanHamburger.setHanbao(drink);
        System.out.println(drink);
        return this;
    }

    @Override
    Waiter executeC(String chip) {
        hanHamburger.setHanbao(chip);
        System.out.println(chip);
        return this;
    }

    @Override
    Waiter executeD(String cheese) {
        hanHamburger.setHanbao(cheese);
        System.out.println(cheese);
        return this;
    }

    @Override
    Hamburger gethamburger() {

        return hanHamburger;
    }


}

package cn.hhw.designModel.factory.builder.demo3;

/**
 * Author: jyh
 * Date: 2020/8/27 23:26
 * Content:指挥者
 */
public class Consumer {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        //链式编程
       // waiter.executeA("鸡腿皇堡").executeB("可乐两杯").executeC("巧克力奶酪");
        waiter.executeA("鸡腿皇堡");
        waiter.executeB("可乐两杯");
        waiter.executeC("巧克力奶酪");

        //这里要是执行D步骤,就是默认值
        Hamburger gethamburger = waiter.gethamburger();
        System.out.println(gethamburger);
    }
}



结语:指挥者在建造者模式中有重要的作用,通常是知道建造者如何构建产品,并向建造者返回完整的产品,有时是可以简化的,通常会把指挥的权利交给用户,通过静态内部类的方式实现零件无需装配构造,这种方式更加灵活,也更符合定义,内部类有复杂对象的默认实现,使用时可以根据需求自由更改内容,无需改变具体的构造方法,就可以生产出不同的复杂产品 缺点是如果产品内部变化复杂,就需要定义很多具有建造者,导致系统变得很庞大

3.5、原型模式

protoType

对复杂类的直接克隆引用,减少重新构建过程

package cn.hhw.designModel.factory.cloneModel;

import java.util.Date;

/**
 * Author: jyh
 * Date: 2020/8/28 20:45
 * Content:需要被克隆的类
 * 1.实现cloneable 表示 这个类可以被克隆
 * 在不实现Cloneable接口的实例上调用对象的克隆方法导致抛出异常CloneNotSupportedException 。
 * 2.重写父类的object方法
 */
public class User implements Cloneable {
    private int id;
    private String name;
    private Date birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User clone = (User)super.clone();
        clone.birthday.clone();
        return  clone;

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

package cn.hhw.designModel.factory.cloneModel;

import javax.sound.midi.Soundbank;
import java.util.Date;

/**
 * Author: jyh
 * Date: 2020/8/28 20:49
 * Content:
 */
public class Test  {
    public static void main(String[] args) throws CloneNotSupportedException {
        //此处有一个问题,如果改变原对象的id,name,克隆对象,并不会改变,但如果改变了原对象的birthday,那么clone对象的这个字段值
        //也会改变。原因是date是引用的,所以需要将在类中将date也克隆
        Date date = new Date();
        User user1 = new User();
        user1.setId(1);
        user1.setName("zhangsan");
        user1.setBirthday(date);
        System.out.println(user1);
        System.out.println("========================================");
        User user2 = (User) user1.clone();
        System.out.println(user2);

        user1.setBirthday(date);
        user1.setName("wangwu");
        System.out.println(user1);
        System.out.println(user2);

    }
}

原型模式就是对一个构建好的对象进行直接复制,然后使用,减少了一些复杂的构建过程,提高了复用性

4、结构型模式

适配器模式,

将一个类的接口转换成客户希望的另外一个接口,使得原本不兼容不可以在一起工作的类可以在一起工作

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:25
 * Content: Target 网线,可以上网
 */
public class Intel {

    public void connectionNetwork(){

        System.out.println("可以上网啦!!!!(*^▽^*)");
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:28
 * Content:类适配器,继承网线类,则有网线的上网方法
 *对象适配器
 */
public class Adapter extends Intel {

    @Override
    public void connectionNetwork() {
        super.connectionNetwork();
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:24
 * Content:笔记本电脑,需要连接到网线类,但是接口不同,不能直接使用,需要一个中间适配器类来完成这个动作
 */
public class Laptop {
    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        //连接到适配器
        connectAdap(adapter);
    }
    
    public static void  connectAdap( Adapter adapter){
        adapter.connectionNetwork();
    }
}

package cn.hhw.designModel.factory.adapter;

/**
 * Author: jyh
 * Date: 2020/8/28 21:28
 * Content:类适配器,继承网线类,则有网线的上网方法
 *对象适配器 对于不同的要求,则使用不同的对象进行处理
 * 适配器,其实应该定义为接口
 */
public class Adapter  {

    private Intel intel;

    public Adapter() {
        this.intel = new Intel();
    }


    public void connectionNetwork() {
        intel.connectionNetwork();
    }
}

结语:三种角色定义,目标接口,用户所需要连接到的真正目标类,可以是具体的实现,也可以是抽象类或接口,就好像用户需要上网,这个目标就是网线类

需要适配的类,这里对应的就是电脑,电脑需要适配,那电脑就是需要被适配的类

适配器:通过包装一个需要适配的对象,吧源接口转换成目标对象

一个对象适配器可以把多个不同的适配者配到同一个目标

桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式

5、行为型模式

模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式

你可能感兴趣的:(设计模式,java,spring,后端)