GoF23种设计模式

23种设计模式

设计模式的分类 总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

OOP七大原则

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

里氏替换原则:继承必须确保超累所拥有的性质在子类中任然成立(尽量不重写父类的方法)

依赖倒置原则:要面向接口编程,不要面向实现编程

单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性

接口隔离原则:要为各个类创建他们需要的专用接口

迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话

合成复用原则:尽量先试用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

创建型模式

单例模式:

            一个类有且仅有一个实例,并且自行实例化向整个系统提供。

应用场景:如:线程池,数据库连接池...!

饿汉式 DCL懒汉式,深究!

饿汉式:

类加载的 初始化阶段就完成了实例的初始化。本质上就是借助了Jvm类加载机制,保证实例的唯一性!

  • 加载二进制数据到内存中,生成对应的Class数据结构
  • 连接:a.验证,b.准备(给类的静态成员变量赋默认值),c.解析
  • 初始化:给类的静态变量赋初值

只有在真正使用对应的类时,才会触发初始化如(当前类是启动类是main函数所在类),直接进行new操作,访问静态属性、访问静态方法,用反射访问类,初始化一个类的子类等!

GoF23种设计模式_第1张图片

单例模式首先将构造器私有

// 饿汉式单例
 public class Hungry {
 ​
     //可能会浪费空间
     private byte[] date1 = new byte[1024*1024];
     private byte[] date2 = new byte[1024*1024];
     private byte[] date3 = new byte[1024*1024];
     private byte[] date4 = new byte[1024*1024];
 //私有构造器
     private Hungry(){
 ​
     }
 ​
     private final static Hungry HUNGRY = new Hungry();
 ​
     public static Hungry getInstance(){
         return HUNGRY;
     }
 }
DCL懒汉式
懒汉式
  • 懒汉模式:延迟加载,只有在真正使用的时候,才开始实例化!
  • 线程安全问题
  • double check 加锁优化
  • 编译器(JIT),CPU有可能对指令进行指令重排,导致使用到尚未初始化的实例,可以通过添加volatile关键字进行修饰,对于volatile修饰的字段,可以防止指令重排!
//懒汉式单例
 //道高一尺,魔高一丈!
 public class LazyMan {
 ​
     // 通过红路灯标志位!
     private static boolean qinjiang = false;
 ​
     //构造器私有
     private LazyMan(){
         synchronized (LazyMan.class){
             if (qinjiang == false){
                 qinjiang = true;
             }else {
                 throw new RuntimeException("不要试图使用反射破坏异常");
             }
         }
     }
 ​
     private volatile static LazyMan lazyMan;    //volatile 避免指令重排,保证线程间的可见性
 ​
     //双重检测锁模式的 懒汉式单例 DCL懒汉式
     public static LazyMan getInstance() {
         if (lazyMan == null) {
             synchronized (LazyMan.class){
 ​
                 if (lazyMan == null) {
                     lazyMan = new LazyMan();//不是一个原子性操作
                 }
             }
         }
         return lazyMan;
 ​
     }
 ​
     public static void main(String[] args) throws Exception {
        // LazyMan instance = LazyMan.getInstance();
         Field qinjiang = LazyMan.class.getDeclaredField("qinjiang");
         qinjiang.setAccessible(true);
 ​
         Constructor declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
         declaredConstructor.setAccessible(true);
         LazyMan instance = declaredConstructor.newInstance();
 ​
         qinjiang.set(instance,false);
 ​
         LazyMan instance2 = declaredConstructor.newInstance();
 ​
 ​
         System.out.println(instance);
         System.out.println(instance2);
 ​
     }
 ​
 ​
 ​
 }
 /**
  * 1.分配内存空间
  * 2.执行构造方法,初始化对象
  * 3.把这个对象指向这个空间
  *
  * 123
  * 132 A
  *     B // 此时还没有完成构造
  */
package singleton;

public class LazySignleton {

    public static void main(String[] args) {
      /*  LazySignleton instance = LazySignleton.getInstance();
        LazySignleton instance2 = LazySignleton.getInstance();
        System.out.println(instance==instance2);*/

        new Thread(()->{
            LazySignleton instance = LazySignleton.getInstance();
            System.out.println(instance);
        }).start();

        new Thread(()->{
            LazySignleton instance2 = LazySignleton.getInstance();
            System.out.println(instance2);
        }).start();

    }

    //1、构造器私有
    private LazySignleton(){

    }
    //2、声明一个静态的属性
    public volatile static LazySignleton install;//在这里使用volatile可以避免指令重排!

    // 在这里我们多线程下会遇到一些问题,所以我们可以铜鼓加锁解决!
    public synchronized static LazySignleton getInstance(){
        if (install==null){
            /*try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            synchronized (LazySignleton.class){
                if (install==null){
                    install = new LazySignleton();
                    /*
                    在字节码层面:JIT、CPU
                            1、分配空间
                            2、初始化
                            3、引用赋值!
                     */
                }
            }
        }
        return install;
    }
}
静态内部类
  • 本质上是利用类的加载机制来保证线程安全
  • 只有在实际使用的时候,才会触发类的初始化
//静态内部类
 public class Holder {
 ​
     //构造器私有
     private Holder(){
 ​
     }
 ​
     public static Holder getInstance(){
         return InnerClass.HOLDER;
     }
 ​
     public static class InnerClass{
         private static final Holder HOLDER = new Holder();
     }
 }
package singleton;

import java.io.*;
import java.lang.reflect.InvocationTargetException;

public class InnerSignleton {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
       /* InnerClassSignleton instance = InnerClassSignleton.getInstance();
        InnerClassSignleton instance2 = InnerClassSignleton.getInstance();
        System.out.println(instance2==instance);*/

        /*new Thread(()->{
            InnerClassSignleton instance = InnerClassSignleton.getInstance();
            System.out.println(instance);
        }).start();

        new Thread(()->{
            InnerClassSignleton instance2 = InnerClassSignleton.getInstance();
            System.out.println(instance2);
        }).start();*/

        /*Constructor declaredConstructor = InnerClassSignleton.class.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        InnerClassSignleton innerClassSignleton = declaredConstructor.newInstance();
        InnerClassSignleton instance = InnerClassSignleton.getInstance();
        System.out.println(innerClassSignleton==instance);*/

        InnerClassSignleton instance = InnerClassSignleton.getInstance();

        //ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("TestSerilable"));
        //oos.writeObject(instance);
        //oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("TestSerilable"));
        InnerClassSignleton object = ((InnerClassSignleton) ois.readObject());
        System.out.println(object==instance);
    }
}
//我们可以通过序列化来解决我们单例模式的问题!
class InnerClassSignleton implements Serializable {

    static final long serialVersionUID = 42L;

    private static class InnerClassHolder{
        private static InnerClassSignleton install = new InnerClassSignleton();
    }
    private InnerClassSignleton(){
        // 因为反射可以破坏这种异常,所以我们可以进行一个判断抛出异常!静态内部类、懒汉式可以,但是饿汉式没办法!
        if (InnerClassHolder.install!=null){
            throw new RuntimeException("不要试图使用反射破坏!");
        }
    }
    public static  InnerClassSignleton getInstance(){
        return InnerClassHolder.install; //只有在调用返回的时候,才会进行类的初始化!
    }

    Object readResolve() throws ObjectStreamException{
        return InnerClassHolder.install;
    }
}
枚举:Enum

单例不安全,反射

//enum 是什么?  本身也是一个class类
 public enum EnumSingle {
 ​
     INSTANCE;
 ​
     public EnumSingle getInstance(){
         return INSTANCE;
     }
 ​
 }
 class Test{
     public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
         EnumSingle instance = EnumSingle.INSTANCE;
 ​
 ​
 ​
         Constructor declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
         declaredConstructor.setAccessible(true);
         EnumSingle instance1 = declaredConstructor.newInstance();
 ​
        //  NoSuchMethodException: com.kuang.single.EnumSingle.()
         System.out.println(instance);
         System.out.println(instance1);
 ​
     }
 }
package singleton;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;

public enum EnumSingleton {

    INSTANCE;

    public void print(){
        System.out.println(this.hashCode());
    }
}
// 测试发现枚举天然生成序列化!
class Test{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
       /* EnumSingleton instance = EnumSingleton.INSTANCE;
        EnumSingleton instance2 = EnumSingleton.INSTANCE;
        System.out.println(instance2==instance);*/

       /* Constructor declaredConstructor = EnumSingleton.class.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        EnumSingleton enumSingleton = declaredConstructor.newInstance();
        System.out.println(enumSingleton);*/

        EnumSingleton instance = EnumSingleton.INSTANCE;

        //ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("enumsigleton"));
        //oos.writeObject(instance);
        //oos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("enumsigleton"));
        EnumSingleton object = (EnumSingleton) ois.readObject();
        System.out.println(instance==object);
    }
}

枚举最终反编译:

javap -p 文件名

下载反编译工具将class文件反编译!

工厂模式

简单工厂模式

:简单工厂模式是属于创建型模式,又叫做静态工厂方法模式

例如:(直接看代码)

先写一个接口

public interface Car {
     void name();
 }

定义他的工厂类

//静态工厂模式
 //增加一个新的产品,如果不修改代码,做不到!
 ​
 //开闭原则
 public class CarFactory {
 ​
     //方法一:
     public static Car getCar(String car){
         if (car.equals("五菱")){
             return new WuLing();
         }else if (car.equals("特斯拉")){
             return new Tesla();
         }else {
             return null;
         }
     }
 ​
     //方法二:
     public static Car getWuLing(){
         return new WuLing();
     }
     public static Car getTesla(){
         return new Tesla();
     }
 }

汽车的品牌实现接口

public class Dazhong implements Car{
     @Override
     public void name() {
         System.out.println("大众!");
     }
 }
public class Tesla implements Car{
     @Override
     public void name() {
         System.out.println("特斯拉!");
     }
 }
public class WuLing implements Car{
     @Override
     public void name() {
         System.out.println("五菱宏光!");
     }
 }

消费者买车

public class Consumer {
     public static void main(String[] args) {
         //接口,所有的实现类!工厂
         //Car car = new WuLing();
         //Car car2 = new Tesla();
 ​
         //2.使用工厂类实现
 ​
         Car car = CarFactory.getCar("五菱");
         Car car2 = CarFactory.getCar("特斯拉");
 ​
         car.name();
         car2.name();
     }
 }
工厂方法模式

:是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。

定义接口

public interface Car {
     void name();
 }

定义车工厂

//工厂方法模式
 public interface CarFactory {
     Car getCar();
 }

车品牌工厂 :实现车工厂接口

public class MoBaiFactory implements CarFactory{
     @Override
     public Car getCar() {
         return new MoBai();
     }
 }
public class TeslaFactory implements CarFactory{
     @Override
     public Car getCar() {
         return new Tesla();
     }
 }
public class WuLingFactory implements CarFactory{
     @Override
     public Car getCar() {
         return new WuLing();
     }
 }

汽车:实现Car接口

public class MoBai implements Car{
     @Override
     public void name() {
         System.out.println("摩拜单车!");
     }
 }
public class Tesla implements Car {
     @Override
     public void name() {
         System.out.println("特斯拉!");
     }
 }
public class WuLing implements Car {
     @Override
     public void name() {
         System.out.println("五菱宏光!");
     }
 }

消费者可以直接去车工厂提取车,不需要考虑其他

public class Consumer {
     public static void main(String[] args) {
         Car car = new WuLingFactory().getCar();
         Car car2 = new TeslaFactory().getCar();
 ​
         car.name();
         car2.name();
         Car car3 = new MoBaiFactory().getCar();
         car3.name();
     }
 }
package factory;
// 简单工厂与方法工厂模式!
public class FactoryMethod {

    public static void main(String[] args) {
        Application application = new ConcreateProductA();
        Product product = application.getObject();
        product.method1();
    }

}

interface Product{
    public void method1();
}

class ProductA implements Product{
    @Override
    public void method1(){
        System.out.println("A  method1 start...");
    }
}

class ProductB implements Product{
    @Override
    public void method1(){
        System.out.println("B  method1 start...");
    }
}

class SimpleFactory{
    public static Product createProduct(String type){
        if (type.equals("A")){
            return new ProductA();
        }else if(type.equals("B")){
            return new ProductB();
        }else {
            return null;
        }
    }
}

abstract class Application{

    abstract Product createProduct();

    Product getObject(){
        Product product = createProduct();

        return product;

    }
}

class ConcreateProductA extends Application{
    @Override
    Product createProduct() {
        return new ProductA();
    }
}

class ConcreateProductB extends Application{
    @Override
    Product createProduct() {
        return new ProductB();
    }
}

应用场景

  • 当你不知道该如何使用对象的确切类型的时候
  • 当你希望为库或框架提供扩展的及其内部组件的方法时

抽象工厂模式

:抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。

public interface IProductFactory {
 //产品工厂 、生产手机与路由器
     //生产手机
     IphoneProduct  iphoneProduct();
 ​
     //生产路由器
     IRouterProduct routerProduct();
 }
//手机产品接口
 public interface IphoneProduct {
 ​
     void start();
     void shutdown();
     void callup();
     void sendSMS();
 ​
 }
public interface IRouterProduct {
 //路由器产品接口
     void start();
     void shutdown();
     void openWifi();
     void setting();
 ​
 }

不同手机工厂:需要实现产品接口,并且重写方法

public class HuaweiFactory implements IProductFactory{
     @Override
     public IphoneProduct iphoneProduct() {
         return new HuaweiIphone();
     }
 ​
     @Override
     public IRouterProduct routerProduct() {
         return new HuaweiIRouter();
     }
 }
public class XiaomiFactory implements IProductFactory{
     @Override
     public IphoneProduct iphoneProduct() {
         return new XiaomiPhone();
     }
 ​
     @Override
     public IRouterProduct routerProduct() {
         return new XiaomiIRouter();
     }
 }

不同手机实现手机接口

//华为手机
 public class HuaweiIphone implements IphoneProduct{
     @Override
     public void start() {
         System.out.println("开启华为手机");
     }
 ​
     @Override
     public void shutdown() {
         System.out.println("关闭华为手机");
     }
 ​
     @Override
     public void callup() {
         System.out.println("华为手机打电话");
     }
 ​
     @Override
     public void sendSMS() {
         System.out.println("华为发短信");
     }
 }
//小米手机
 public class XiaomiPhone implements IphoneProduct{
     @Override
     public void start() {
         System.out.println("开启小米手机");
     }
 ​
     @Override
     public void shutdown() {
         System.out.println("小米手机关机");
     }
 ​
     @Override
     public void callup() {
         System.out.println("小米打电话");
     }
 ​
     @Override
     public void sendSMS() {
         System.out.println("小米发短信");
     }
 }
//华为路由器
 public class HuaweiIRouter implements IRouterProduct{
     @Override
     public void start() {
         System.out.println("启动华为路由器");
     }
 ​
     @Override
     public void shutdown() {
         System.out.println("关闭华为路由器");
     }
 ​
     @Override
     public void openWifi() {
         System.out.println("打开华为wifi");
     }
 ​
     @Override
     public void setting() {
         System.out.println("华为设置");
     }
 }
//小米路由器
 public class XiaomiIRouter implements IRouterProduct{
     @Override
     public void start() {
         System.out.println("启动小米路由器");
     }
 ​
     @Override
     public void shutdown() {
         System.out.println("关闭小米路由器");
     }
 ​
     @Override
     public void openWifi() {
         System.out.println("打开小米wifi");
     }
 ​
     @Override
     public void setting() {
         System.out.println("小米设置");
     }
 }
package factory;

//简单理解:这里的抽象工厂模式,就是我们抽象方法实现的组合!
public class AbstractFactory {

    public static void main(String[] args) {
        //MysqlDataBaseUtils utils = new MysqlDataBaseUtils();
        OracleDataBaseUtils utils = new OracleDataBaseUtils();
        Iconnection connection = utils.getConnection();
        connection.connect();
        IConmand command = utils.getCommand();
        command.command();
    }
}

//这里我们模拟 :变化 :mysql、oracle...
        // connection 、command...

interface Iconnection{
    void connect();
}

interface IConmand{
    void command();
}

interface IDatabaseUtils{
    Iconnection getConnection();
    IConmand getCommand();
}

class MysqlConnection implements Iconnection{
    @Override
    public void connect() {
        System.out.println("mysql connection...");
    }
}


class MysqlCommand implements IConmand{

    @Override
    public void command() {
        System.out.println("mysql command...");
    }
}


class MysqlDataBaseUtils implements IDatabaseUtils{
    @Override
    public Iconnection getConnection() {
        return new MysqlConnection();
    }

    @Override
    public IConmand getCommand() {
        return new MysqlCommand();
    }
}

class OracleConnection implements Iconnection{
    @Override
    public void connect() {
        System.out.println("oracle connection...");
    }
}


class OracleCommand implements IConmand{

    @Override
    public void command() {
        System.out.println("oracle command...");
    }
}


class OracleDataBaseUtils implements IDatabaseUtils{
    @Override
    public Iconnection getConnection() {
        return new OracleConnection();
    }

    @Override
    public IConmand getCommand() {
        return new OracleCommand();
    }
}

建造者模式

( Builder ):建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

例:工地建房子

//抽象的建造者:方法
 public abstract class Builder {
 ​
     //步骤:A->B->C->D
     abstract void buildA();//地基
     abstract void buildB();//钢筋工程
     abstract void buildC();//铺电线
     abstract void buildD();//粉刷
 ​
     //完工:得到产品
     abstract Product getProduct();
 }
//产品:房子
 public class Product {
     private String buildA;
     private String buildB;
     private String buildC;
     private String buildD;
 ​
     public String getBuildA() {
         return buildA;
     }
 ​
     public void setBuildA(String buildA) {
         this.buildA = buildA;
     }
 ​
     public String getBuildB() {
         return buildB;
     }
 ​
     public void setBuildB(String buildB) {
         this.buildB = buildB;
     }
 ​
     public String getBuildC() {
         return buildC;
     }
 ​
     public void setBuildC(String buildC) {
         this.buildC = buildC;
     }
 ​
     public String getBuildD() {
         return buildD;
     }
 ​
     public void setBuildD(String buildD) {
         this.buildD = buildD;
     }
 ​
     @Override
     public String toString() {
         return "Product{" +
                 "buildA='" + buildA + '\'' +
                 ", buildB='" + buildB + '\'' +
                 ", buildC='" + buildC + '\'' +
                 ", buildD='" + buildD + '\'' +
                 '}';
     }
 }

定义一个工人类

public class Worker extends Builder{
 ​
     private Product product;
 ​
     public Worker() {
         product = new Product();
     }
 ​
     @Override
     void buildA() {
         product.setBuildA("地基");
         System.out.println("地基");
     }
 ​
     @Override
     void buildB() {
         product.setBuildB("钢筋工程");
         System.out.println("钢筋工程");
     }
 ​
     @Override
     void buildC() {
         product.setBuildC("铺电线");
         System.out.println("铺电线");
     }
 ​
     @Override
     void buildD() {
         product.setBuildD("粉刷");
         System.out.println("粉刷");
     }
 ​
     @Override
     Product getProduct() {
         return product;
     }
 }

定义指挥者:负责指挥工人

//指挥:核心。负责指挥构建一个工程,工程如何构建,由他指挥
 public class Director {
     public Product build(Builder builder){
 ​
         //指挥工人按照顺序建房子
         builder.buildA();
         builder.buildB();
         builder.buildC();
         builder.buildD();
 ​
         return builder.getProduct();
     }
 ​
 }

测试:

public class Test {
     public static void main(String[] args) {
         //指挥
         Director director = new Director();
 ​
         //指挥  具体的工人完成  产品
         Product build = director.build(new Worker());
         System.out.println(build.toString());
     }
 }
public abstract class Builder {
 ​
 ​
     abstract Builder buildeA(String msg);//汉堡
     abstract Builder buildeB(String msg);//可乐
     abstract Builder buildeC(String msg);//薯条
     abstract Builder buildeD(String msg);//甜点
 ​
     abstract Product getProduct();
 }

套餐

//产品:套餐
 public class Product {
 ​
     private String BuildA="汉堡";
     private String BuildB="可乐";
     private String BuildC="薯条";
     private String BuildD="甜点";
 ​
     public String getBuildA() {
         return BuildA;
     }
 ​
     public void setBuildA(String buildA) {
         BuildA = buildA;
     }
 ​
     public String getBuildB() {
         return BuildB;
     }
 ​
     public void setBuildB(String buildB) {
         BuildB = buildB;
     }
 ​
     public String getBuildC() {
         return BuildC;
     }
 ​
     public void setBuildC(String buildC) {
         BuildC = buildC;
     }
 ​
     public String getBuildD() {
         return BuildD;
     }
 ​
     public void setBuildD(String buildD) {
         BuildD = buildD;
     }
 ​
     @Override
     public String toString() {
         return "Product{" +
                 "BuildA='" + BuildA + '\'' +
                 ", BuildB='" + BuildB + '\'' +
                 ", BuildC='" + BuildC + '\'' +
                 ", BuildD='" + BuildD + '\'' +
                 '}';
     }
 }
//具体的建造者
 public class Worker extends Builder{
 ​
     private Product product;
 ​
     public Worker() {
         product = new Product();
     }
 ​
     @Override
     Builder buildeA(String msg) {
         product.setBuildA(msg);
         return this;
     }
 ​
     @Override
     Builder buildeB(String msg) {
         product.setBuildB(msg);
         return this;
     }
 ​
     @Override
     Builder buildeC(String msg) {
         product.setBuildC(msg);
         return this;
     }
 ​
     @Override
     Builder buildeD(String msg) {
         product.setBuildD(msg);
         return this;
     }
 ​
     @Override
     Product getProduct() {
         return product;
     }
 ​
 ​
 }

用户可以自己搭配选择

public class Test {
     public static void main(String[] args) {
 ​
         //服务员
         Worker worker = new Worker();
 ​
         //链式编程  : 在原来的基础上,可以自由组合了,如果不组合,也有默认的套餐
         Product product = worker.buildeA("全家桶").buildeB("雪碧")
                 .getProduct();
         System.out.println(product.toString());
     }
 }

 

原型模式

:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

复制拷贝: 第一个方案复制的会跟之前的共用一个时间

/*
 1.实现一个接口     Cloneable
 2.重写一个方法     clone()
 */
 ​
 ​
 //Video
 public class Video implements Cloneable{
 ​
     private String name;
     private Date createTime;
 ​
     @Override
     protected Object clone() throws CloneNotSupportedException {
         return super.clone();
     }
 ​
     public Video() {
     }
 ​
     public Video(String name, Date createTime) {
         this.name = name;
         this.createTime = createTime;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public Date getCreateTime() {
         return createTime;
     }
 ​
     public void setCreateTime(Date createTime) {
         this.createTime = createTime;
     }
 ​
     @Override
     public String toString() {
         return "Video{" +
                 "name='" + name + '\'' +
                 ", createTime=" + createTime +
                 '}';
     }
 }
public class Bilibili {
 ​
     public static void main(String[] args) throws CloneNotSupportedException {
         //原型对象  v1
 ​
         Date date = new Date();
         Video v1 = new Video("狂神说JAVA", date);
         System.out.println("v1=>"+v1);
         System.out.println("v1=>hash"+v1.hashCode());
 ​
         //v1  克隆  v2
         //Video v2 = new Video("狂神说JAVA", date);
         Video v2 = (Video) v1.clone();
         System.out.println("v2=>"+v2);
         System.out.println("v2=>hash"+v2.hashCode());
 ​
     }
 }

第二个在修改时间的情况下会分隔开

/*
 1.实现一个接口     Cloneable
 2.重写一个方法     clone()
 */
 ​
 ​
 //Video
 public class Video implements Cloneable{
 ​
     private String name;
     private Date createTime;
 ​
     @Override
     protected Object clone() throws CloneNotSupportedException {
 ​
         Object obj = super.clone();
 ​
         //实现深克隆~  序列化、反序列化
         Video v = (Video) obj;
         v.createTime = (Date)this.createTime.clone();//将这个对象的属性进行克隆
 ​
         return obj;
     }
 ​
     public Video() {
     }
 ​
     public Video(String name, Date createTime) {
         this.name = name;
         this.createTime = createTime;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public Date getCreateTime() {
         return createTime;
     }
 ​
     public void setCreateTime(Date createTime) {
         this.createTime = createTime;
     }
 ​
     @Override
     public String toString() {
         return "Video{" +
                 "name='" + name + '\'' +
                 ", createTime=" + createTime +
                 '}';
     }
 }
//Spring Bean:单例模式,原型模式~
 // 原型模式 + 工厂模式 ==> new <==> 原型模式
 ​
 public class Bilibili {
 ​
     public static void main(String[] args) throws CloneNotSupportedException {
 ​
         //原型对象  v1
 ​
         Date date = new Date();
         Video v1 = new Video("狂神说JAVA", date);
         Video v2 = (Video) v1.clone();
 ​
         System.out.println("v1=>"+v1);
         System.out.println("v2=>"+v2);
         System.out.println("======================");
         date.setTime(231321312);
 ​
         System.out.println("v1=>"+v1);
         System.out.println("v2=>"+v2);
 ​
      /*
         //原型对象  v1
 ​
         Date date = new Date();
         Video v1 = new Video("狂神说JAVA", date);
         System.out.println("v1=>"+v1);
         System.out.println("v1=>hash"+v1.hashCode());
 ​
         //v1  克隆  v2
         //Video v2 = new Video("狂神说JAVA", date);
         Video v2 = (Video) v1.clone();
         System.out.println("v2=>"+v2);
         System.out.println("v2=>hash"+v2.hashCode());
     */
     }
 }

结构型模式

适配器模式

:是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

GoF23种设计模式_第2张图片

//接口转换器的抽象实现
 public interface NetToUsb {
 ​
     //作用:处理请求,网线=>usb
     public void handleRequest();
 }
//要被适配的类    :网线
public class Adaptee {

    public void request(){

        System.out.println("连接网线上网");
    }
}
//1.继承  (类适配器,单继承)----
//2.组合  (对象适配器,常用)


//真正的适配器~,需要连接USB,连接网线~
public class Adapter extends Adaptee implements NetToUsb{

    @Override
    public void handleRequest() {
        super.request();//可以上网了~
    }
}
//1.继承  (类适配器,单继承)
//2.组合  (对象适配器,常用)------


//真正的适配器~,需要连接USB,连接网线~
public class Adapter2  implements NetToUsb{

    private Adaptee adaptee;

    public Adapter2(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void handleRequest() {
        adaptee.request();//可以上网了~
    }
}
//客户端类:想上网,插不上网线~
public class Computer {

    //我们的电脑需要连接上转接器才可以上网
    public void net(NetToUsb adapter) {
        //上网的具体实现~,找一个转接头
        adapter.handleRequest();
    }


    public static void main(String[] args) {
        //电脑,网线,适配器~
        Computer computer = new Computer();//电脑
        Adaptee adaptee = new Adaptee();//网线
        Adapter2 adapter = new Adapter2(adaptee);//转接器  (比较完美的实现)
        //Adapter adapter = new Adapter();//转接器


        computer.net( adapter);
    }
}

桥接模式

:是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(interface)模式。

结构图:

GoF23种设计模式_第3张图片

//品牌
public interface Brand {

    void info();

}
//苹果
public class Apple implements Brand{
    @Override
    public void info() {
        System.out.print("苹果");
    }
}
//联想
public class Lenovo implements Brand{
    @Override
    public void info() {
        System.out.print("联想");
    }
}
//抽象的电脑类
public abstract class Computer {

    //组合,品牌~
    protected Brand brand;

    public Computer(Brand brand) {
        this.brand = brand;
    }

    public void info(){
        brand.info();//自带品牌
    }
}

class Desktop extends Computer{
    public Desktop(Brand brand) {
        super(brand);
    }

    @Override
    public void info() {
        super.info();
        System.out.println("台式机");
    }
}

class Laptop extends Computer{
    public Laptop(Brand brand) {
        super(brand);
    }

    @Override
    public void info() {
        super.info();
        System.out.println("笔记本");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        //苹果笔记本
        Computer computer = new Laptop(new Apple());
        computer.info();

        //联想台式机
        Computer computer2 = new Desktop(new Lenovo());
        computer2.info();
    }
}

结构:(同理上面的图)

GoF23种设计模式_第4张图片

代理模式

为什么要学习代理模式?这就是SpringAOP的底层! 【SpringAOP 和 SpringMVC】

代理模式的分类:

  • 静态代理

  • 动态代理

GoF23种设计模式_第5张图片

1.静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决

  • 真是角色:被代理的角色

  • 代理角色:代理真实角色,代理真实角色后一般会做一些附属操作

  • 客户:访问代理对象的人!

代码步骤:

1.接口

//租房
public interface Rent {

    public void rent();
}

2.真实角色

//房东
public class Landlord implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

3.代理角色

public class Proxy implements Rent{

    private Landlord landlord;

    public Proxy() {
    }

    public Proxy(Landlord landlord) {
        this.landlord = landlord;
    }

    @Override
    public void rent() {
        seeHouse();
        landlord.rent();
        hetong();
        fee();
    }

    public void seeHouse(){
        System.out.println("中介带你看房");
    }

    public void fee(){
        System.out.println("收中介费");
    }

    public void hetong(){
        System.out.println("签租赁合同");
    }
}

4.客户端访问代理角色

public class Client {

    public static void main(String[] args) {
        //房东要出租房子
        Landlord landlord = new Landlord();
        //代理,中介帮房东出租房子,但是呢?代理角色一般会有一些附属操作
        Proxy proxy = new Proxy(landlord);
        //你不用面对房东,直接找中介租房子即可!
        proxy.rent();
    }

}

代理模式的好处:

  • 可以使真是角色的操作更加纯粹!不用去关注一些公共的业务

  • 公共的业务也就交给代理角色!实现了业务的分工!

  • 公共业务发生拓展的时候,方便集中管理!

缺点:

  • 一个真是角色就会产生一个代理角色:代码量会翻倍~ 开发效率会变低~

2.加深理解静态代理

代码:

1.接口

public interface UserService {

    public void add();
    public void delete();
    public void update();
    public void query();
}

2.实现类

//真实对象
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询了一个用户");
    }
    //1、改动原有的业务代码,在公司中是大忌!
}

3.代理

public class UserServiceProxy implements UserService{

    UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    @Override
    public void update() {
        log("update");
        userService.update();
    }

    @Override
    public void query() {
        log("query");
        userService.query();
    }

    //日志方法
    public void log(String msg){
        System.out.println("使用了[Debug]"+msg+"方法");
    }
}

4.客户端访问

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();

        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);

        proxy.add();
    }
}

GoF23种设计模式_第6张图片

3.动态代理
  • 动态代理和静态代理角色一样

  • 动态代理的代理类是动态的,不是我们直接写好的!

  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理

    • 基于接口- - - JDK动态代理【我们在这里使用】

    • 基于类:cglib

    • Java字节码实现:javasist

需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使真是角色的操作更加纯粹!不用去关注一些公共的业务

  • 公共的业务也就交给代理角色!实现了业务的分工!

  • 公共业务发生拓展的时候,方便集中管理!

  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务

  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!

代码:

1.接口

//租房
public interface Rent {

    public void rent();
}

2.真实对象

//房东
public class Landlord implements Rent {
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

3.代理

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //动态代理的本质,就是反射机制的实现!
        seeHouse();
        Object result = method.invoke(rent,args);
        return result;
    }

    public void seeHouse(){
        System.out.println("中介带看房子");
    }
}

4.客户端访问对象

public class Client {

    public static void main(String[] args) {
        //真实角色
        Landlord landlord = new Landlord();

        //代理角色:现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //通过调用程序处理角色来处理我们要调用的接口对象!
        pih.setRent(landlord);
        Rent proxy = (Rent) pih.getProxy();//这里的proxy就是动态生成的,我们并没有写!
        proxy.rent();
    }
}

优化动态代理万能的方法:

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }


    //生成得到代理类
    public Object getProxy(){//最后面的this代表实现的接口  InvocationHandler
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        log(method.getName());
        //动态代理的本质,就是反射机制的实现!
        Object result = method.invoke(target,args);
        return result;
    }

    public void log (String msg){
        System.out.println("使用了"+msg+"方法");
    }
}
public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色,不存在
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        pih.setTarget(userService);//设置要代理的对象
        //动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.query();
    }
}

你可能感兴趣的:(设计模式,单例模式,java,开发语言)