菜鸟学JAVA之——几种设计模式(单例、代理、工厂、建造者)

一、单例设计模式(SingIton)🐶

1.饿汉式(线程安全)
  • 1.私有化类的构造器
  • 2.内部创建类的对象
  • 4.要求此对象也必须声明为静态的
  • 3.提供公共的静态的方法,返回类的对象
public class SingletonTest1 {
    public static void main(String[] args) {
        Bank1 bank1 = Bank1.getInstance();
        Bank1 bank2 = Bank1.getInstance();
        System.out.println(bank1==bank2);
    }
}

//饿汉式
class Bank1 {

    //1.私有化类的构造器
    private Bank1() {

    }

    //2.内部创建类的对象
    //4.要求此对象也必须声明为静态的
    private static Bank1 instance = new Bank1();

    //3.提供公共的静态的方法,返回类的对象
    public static Bank1 getInstance() {
        return instance;
    }
}
2.懒汉式(线程不安全)
  • 1.私有化类的构造器
  • 2.声明当前类对象,没有初始化
  • 4.此对象也必须声明为static的
  • 3.声明public、static的返回当前类对象的方法
public class SingletonTest2 {
    public static void main(String[] args) {
        Bank2 bank1 = Bank2.getInstance();
        Bank2 bank2 = Bank2.getInstance();
        System.out.println(bank1 == bank2);
    }
}

//懒汉式
class Bank2 {
    //1.私有化类的构造器
    private Bank2() {

    }

    //2.声明当前类对象,没有初始化
    //4.此对象也必须声明为static的
    private static Bank2 instance = null;

    //3.声明public、static的返回当前类对象的方法
    public static Bank2 getInstance() {
        if (instance == null) {
            //①
            instance = new Bank2();
        } 
        return instance;
    }
}

解释一下这种模式为啥不安全:未加锁,在多线程中,第一个线程进入,判断instance为空,进入if在①处,恰好时间片用完了,他不能继续执行了,等待其他线程执行,他也并没有获得锁,没有锁住任何东西,这时第二个线程进来了,这时instance还是空的,也进入了①的位置,时间片也用完了,这时第一个线程执行,第一个线程从①处动身,直接创建一个对象,返回了对象,第二个线程也判断完了从①开始,创建了一个新对象,返回。这样两个线程拿到的对象就不是同一个对象,违背了单例设计模式的原则。

3.懒汉式(线程安全)
public class BankTest {
    public static void main(String[] args) {

    }
}

class Bank {
    private Bank() {

    }

    private static Bank bank;

    public static Bank getBank() {
        //方式一:效率稍差(不管有没有给bank实例化上对象,进来的线程都需要等待)
//        synchronized (Bank.class) {
//            if(bank == null) {
//                bank = new Bank();
//            }
//            return bank;
//        }
        //方式二(双重检查锁模式):效率更高
        if(bank == null) {
            synchronized (Bank.class) {
                if(bank == null) {
                    bank = new Bank();
                }
            }
        }
        return bank;
    }
}

如果是单一线程,推荐使用饿汉模式和懒汉模式(线程不安全的),如果是多线程,并发抢占很激烈的情况,推荐使用双重检查锁模式

二、代理模式(proxy)

什么是代理模式?就是将原本需要你做的事情,现在不需要你做,交付给了一个跟你非常类似的人代替你做。(一个小伙喜欢一个女生,天天给她写信,然后那个女孩爱上了邮递员。💘这个邮递员就相当于他的代理,帮他送信)

要求:

  • 1.必须要有代理类(proxy)和被代理类(target)
  • 2.代理类和被代理类必须是同一个接口或者抽象类、类的子类,一般都是接口
  • 3.在代理类里创建一个目标对象target,并且构造方法初始化它
  • 4.在代理类中重写接口的方法,调用被代理类的执行的方法(真正执行工作的是被代理类)
public interface ITPInterface {
    void foo();
}
public class Proxy implements ITPInterface {
    private ITPInterface target;

    public Proxy(ITPInterface target) {
        this.target = target;
    }

    @Override
    public void foo() {
        target.foo();
    }
}
public class Target implements ITPInterface{

    @Override
    public void foo() {
        System.out.println("你好,我是被代理类!");
    }
}
public class Main {
    public static void main(String[] args) {
        ITPInterface itpInterface = new Proxy(new Target());
        itpInterface.foo();
    }
}

可以通过代理模式解开类与类的耦合,让代码执行起来受控程度更加在我们身上,写业务的程序员更加专注于业务。

代理模式的作用就是,你已经完成了业务工作,我可以帮你在代理类中完成这个业务的前置条件和后置条件

修改一下上面的代码,体会一下:

public class Proxy implements ITPInterface {
    private ITPInterface target;

    public Proxy(ITPInterface target) {
        this.target = target;
    }

    @Override
    public void foo(int a, int b) {//如果b为0就会抛异常,把这个过程放到这里解决
        if(b == 0) {
            System.out.println("除数不能为0");
        }
        target.foo(a,b);
        System.out.println("执行完成");
    }
}
public class Target implements ITPInterface{

    @Override
    public void foo(int a, int b) {
        System.out.println("a/b="+a/b);
    }
}

就相当于代理类可以给被代理类多加一些功能、判断。在原有代码的基础上加一些代码实现。被代理类的方法一直都不会变!

三、工厂模式(factory)

工厂能生产的产品一定是与他原有生产的相似的产品,比如塑料厂,让他生产塑料玩具,但是不能炼钢。工厂能生产东西一定是有一个生产模板

  • 1.确定一个生产模板(接口),所有产品类实现这个接口
  • 2.在工厂类中生产这些产品
public interface IUsb {
    void writeData(byte[] bytes);
}
public class Mouse implements IUsb {
    @Override
    public void writeData(byte[] bytes) {
        System.out.println("我是鼠标");
    }
}
public class Flash implements IUsb {
    @Override
    public void writeData(byte[] bytes) {
        System.out.println("我是U盘");
    }
}
public class Factory {
    public static IUsb factory(String args) {
        switch (args) {
            case "mouse":
                return new Mouse();
            case "flash":
                return  new Flash();
            default:
                return null;
        }
    }
}
public class Main {
    public static void main(String[] args) {
        IUsb mouse = Factory.factory("mouse");
        mouse.writeData(null);
        IUsb flash = Factory.factory("flash");
        flash.writeData(null);
    }
}

工厂模式最主要的就是要有模板。比如上面的这个工厂就生产usb的东西,只要你要生产跟usb有关的东西(实现IUsb接口)就可以往这个工厂的流水线里放。然后你要主类中生产这个产品时根本不用new,new的过程放在了工厂里。

四、建造者模式(builder)

  • 创建一个类Target,类里的属性和构造方法都是私有的,且没有set/get方法,其他方法都是公开的,所有的建造过程放在建造者里完成(这个类是建造的目标物)
  • 创建一个建造类TargetBuilder(所有的建造过程写在这个类),Target类有什么属性,这个类就要有什么属性

建造者模式能最大程度上保护Target对象的内部的所有的内容

如果碰到一个类不能直接new他的对象,就可以用这个模式

静态建造者模式:

public class TTarget {
    private int length;
    private String color;

    private TTarget() {

    }

    public void foo() {
        System.out.println(color + "," +length);
    }
}
public class TTargetBuilder {

    private static TTargetBuilder tTargetBuilder = new TTargetBuilder();
    private static int length;
    private static String color;

    private TTargetBuilder() {

    }

    public TTarget build () {
        Class c = TTarget.class;
        try {
            Constructor declaredConstructor = c.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            Object o = declaredConstructor.newInstance();
            Field length = c.getDeclaredField("length");
            length.setAccessible(true);
            length.set(o,this.length);
            Field color = c.getDeclaredField("color");
            color.setAccessible(true);
            color.set(o,this.color);
            return (TTarget) o;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static TTargetBuilder setLength(int length) {
        //this.length = length;//静态方法里不能用this
        tTargetBuilder.length = length;
        return tTargetBuilder;
    }

    public static TTargetBuilder setColor(String color) {
        tTargetBuilder.color = color;
        return tTargetBuilder;
    }
}
public class Main {
    public static void main(String[] args) {
        TTarget tTarget = TTargetBuilder.setColor("黄色").setLength(1000).build();//只有调用build方法才创建对象,可以极大的降低,创建对象耗费的资源
        tTarget.foo();
    }
}

动态建造者模式:

public class TTarget {
    private int length;
    private String color;

    private TTarget() {

    }

    public void foo() {
        System.out.println(color + "," +length);
    }
}
public class TTargetBuilder {

    private int length;
    private String color;

    public TTargetBuilder() {

    }

    public TTarget build () {
        Class c = TTarget.class;
        try {
            Constructor declaredConstructor = c.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            Object o = declaredConstructor.newInstance();
            Field length = c.getDeclaredField("length");
            length.setAccessible(true);
            length.set(o,this.length);
            Field color = c.getDeclaredField("color");
            color.setAccessible(true);
            color.set(o,this.color);
            return (TTarget) o;
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    public TTargetBuilder setLength(int length) {
        this.length = length;
        return this;
    }

    public static TTargetBuilder setColor(String color) {
        this.color = color;
        return this;
    }
}
public class Main {
    public static void main(String[] args) {
        TTarget tTarget = new TTargetBuilder().setColor("黄色").setLength(1000).build();//只有调用build方法才创建对象,可以极大的降低,创建对象耗费的资源
        tTarget.foo();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值