设计模式_

可看c语言中文网介绍
C语言中文网 Java设计模式

单例模式

懒汉式


/**
 * 懒汉式,单例模式
 * 不足:
 * 在多线程环境中存在多个对象,线程不安全
 */
public class LazySingleton {

    private static LazySingleton instance;

    private LazySingleton(){
    }

    public static LazySingleton getInstance(){
        if (instance==null){
            instance = new LazySingleton();
        }
        return instance;
    }

}

饿汉式


/**
 * 饿汉式,单例模式,线程安全
 * 不足:
 * 类加载时就创建对象,该类不管是否使用都存在一个对象
 * 创建对象无法传递参数
 */
public class HungrySingleton {

    private static HungrySingleton instance;

    /**
     * 静态代码块在类加载期间初始化,只执行一次
     */
    static {
        try {
            instance = new HungrySingleton();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 防止通过反射创建对象
     */
    private HungrySingleton() throws Exception {
        if (instance!=null){
                throw new Exception("该类只能有一个实例");
            }
        }

    public static HungrySingleton getInstance(){
        return instance;
    }

}

双重校验


/**
 * 双重校验:单例模式,线程安全
 * 不足:
 * 在第一次创建对象时需要同步
 */
public class DCLSingleton {

    private volatile static DCLSingleton instance;

    private DCLSingleton(){
    }

    public  static DCLSingleton getInstance(){
        if (instance == null){
            synchronized (DCLSingleton.class){
                if (instance == null){
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }

}

静态内部类


/**
 * 静态内部类,单例模式,线程安全,解决饿汉式中无论如何都存在一个对象的问题
 */
public class StaticInnerSingleton {

    private StaticInnerSingleton(){

    }

    public static StaticInnerSingleton getInstance(){
        return InnerClass.instance;
    }

    /**
     * 静态内部类
     */
    private static class InnerClass{
        private static final StaticInnerSingleton instance = new StaticInnerSingleton();
    }

}

枚举


/**
 * 枚举,单例模式,线程安全,防止反射,序列化,克隆
 */
public enum EnumSingleton {

    INSTANCE;

}

单例模式测试类

 public static void main(String[] args) {

        //懒汉式
        /*
        Singleton singleton = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton == singleton2);
        */
        /*
        for (int i =0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<10;j++){
                        System.out.println(LazySingleton.getInstance());
                    }
                }
            }).start();
        }
        */

        //饿汉式
        /*
        for (int i =0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<10;j++){
                        System.out.println(HungrySingleton.getInstance());
                    }
                }
            }).start();
        }
        */

        //双重校验
        /*
        for (int i =0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<10;j++){
                        System.out.println(DCLSingleton.getInstance());
                    }
                }
            }).start();
        }
        */

        //静态内部类
        /*
        for (int i =0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<10;j++){
                        System.out.println(StaticInnerSingleton.getInstance());
                    }
                }
            }).start();
        }
        */

        //枚举
        for (int i =0;i<10;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j=0;j<10;j++){
                        System.out.println(EnumSingleton.INSTANCE);
                    }
                }
            }).start();
        }
    }

反射测试类
用来证明简单单例模式无法做到线程安全(枚举可以做到)
在例子饿汉式中,对构造方法进行添加语句,做判断对象,抛出异常操作,做到反射无法创建新的对象,达到线程安全

public static void main(String[] args) throws Exception {

        HungrySingleton instance = HungrySingleton.getInstance();

        Class<HungrySingleton> cls = HungrySingleton.class;
        //获取类中的所有构造方法
        Constructor<HungrySingleton> constructor = cls.getDeclaredConstructor();
        //设置私有构造方法可访问
        constructor.setAccessible(true);
        //使用反射实例化对象
        HungrySingleton instance2 = constructor.newInstance();
        System.out.println(instance2);

        System.out.println(instance == instance2);

    }

工厂模式

简单工厂

/**
 * 电器工厂,简单工厂类
 */
public class ApplianceFactory {

    /**
     * 生产电器
     * @param type
     * @return
     */
    public static Appliance makeAppliance(String type){
        switch (type){
            case "电视机":
                return new Tv();
            case "冰箱":
                return new IceBox();
        }
        return null;
    }
}

工厂方法

抽象工厂

代理模式

静态代理

/**
 * 抽象主题:房东接口
 */
public interface HouseOwner {

    /**
     * 出租房屋
     */
    public void rent();

    /**
     * 收租
     */
    public void getMoney();

/**
 * 具体主题:民房,城中村房东类
 * 目标对象
 */
public class VillageHouseOwner implements HouseOwner{


    @Override
    public void rent() {
         System.out.println("有床、独立卫生间、热水器、单间:500/月、押一付一");
    }

    @Override
    public void getMoney() {
        System.out.println("收取每月月租、水电费、生活垃圾费");
    }

/**
 * 代理类,房东代理类
 * 代理目标类
 *
 * 缺点:跟目标对象一样实现了抽象业务的接口,一旦抽象业务接口发送改变也必须跟着改变,可以使用动态代理(反射机制)解决
 */
public class HouseOwnerProxy implements HouseOwner{

    /**
     * 代理类中定义目标对象类中的属性
     */
    private HouseOwner houseOwner;

    public HouseOwnerProxy(){

    }

    public HouseOwnerProxy(HouseOwner houseOwner){
        this.houseOwner = houseOwner;
    }

    @Override
    public void rent() {
        houseOwner.rent();
        getProxyFee();
    }

    @Override
    public void getMoney() {
        houseOwner.getMoney();
        procedureFee();
    }

    public void getProxyFee(){
        System.out.println("收取半个月的房租费当做中介费,只收取一次");
    }

    public void procedureFee(){
        System.out.println("每月收取固定手续费50元");
    }

/**
 * 访问
 */
public class Test {
    public static void main(String[] args) {

        //租客直接找到房东租房,把房租交给房东
        VillageHouseOwner villageHouseOwner = new VillageHouseOwner();
        villageHouseOwner.rent();
        villageHouseOwner.getMoney();

        //创建一个代理类对象,构造方法中传入目标对象(被代理的对象)
        HouseOwnerProxy proxy = new HouseOwnerProxy(new VillageHouseOwner());
        //使用代理类租房子和收取租金
        proxy.rent();
        proxy.getMoney();

    }
}

动态代理

/**
 * 抽象主题:房东接口
 */
public interface HouseOwner {

    /**
     * 出租房屋
     */
    public void rent();

    /**
     * 收租
     */
    public void getMoney();

    /**
     * 房子日常保养维护
     */
    public void maintain();

}


/**
 * 具体主题:民房,城中村房东类
 * 目标对象
 */
public class VillageHouseOwner implements HouseOwner {


    @Override
    public void rent() {
         System.out.println("有床、独立卫生间、热水器、单间:500/月、押一付一");
    }

    @Override
    public void getMoney() {
        System.out.println("收取每月月租、水电费、生活垃圾费");
    }

    @Override
    public void maintain() {
        System.out.println("房子日常维护,家电日常维修");
    }
}


/**
 * jdk动态代理类,用来代理目标业务对象,目标对象必须实现接口
 */
public class JDKProxy implements InvocationHandler {

    /**
     * 要代理的目标对象
     */
    private Object targetObject;

    public JDKProxy(){

    }

    public JDKProxy(Object targetObject){
        this.targetObject = targetObject;
    }

    /**
     * 传入目标对象,使用反射机制动态创建代理对象
     * @param targetObject
     * @return
     */
    public Object creatProxy(Object targetObject){
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(
                targetObject.getClass().getClassLoader(),//目标对象类加载器
                targetObject.getClass().getInterfaces(),//目标对象实现的接口
                this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //使用反射动态调用目标对象的方法
        Object invoke = method.invoke(this.targetObject, args);
        if (method.getName().equals("rent")){//判断当前执行的方法是否是rent方法
            getProxyFee();
        }
        if (method.getName().equals("getMoney")){
            procedureFee();
        }
        return invoke;
    }
    public void getProxyFee(){
        System.out.println("收取半个月的房租费当做中介费,只收取一次");
    }

    public void procedureFee(){
        System.out.println("每月收取固定手续费50元");
    }
}


public class Test {
    public static void main(String[] args) {

        JDKProxy proxy = new JDKProxy();
        //创建代理对象
        HouseOwner proxyHouseOwner = (HouseOwner)proxy.creatProxy(new VillageHouseOwner());
        proxyHouseOwner.rent();
        proxyHouseOwner.getMoney();
        proxyHouseOwner.maintain();
    }
}

观察者模式

/**
 * 抽象观察者,粉丝接口
 */
public interface Fans {

    /**
     * 接收消息的方法,接收主题发送过来的消息
     * @param msg
     */
    public void notify(String msg);
}


/**
 * 抽象主题:明星类
 */
public abstract class Star {

    /**
     * 创建一个集合,存放当前抽象主题所有的观察者粉丝对象
     */
    protected List<Fans> list = new ArrayList<>();

    /**
     * 新增观察者对象,粉丝
     * @param fans
     */
    public synchronized void addFans(Fans fans){
        if (!list.contains(fans)){
            list.add(fans);
        }
    }

    /**
     * 移除观察者对象,粉丝
     * @param fans
     */
    public synchronized void removeFans(Fans fans){
        if (list.contains(fans)){
            list.remove(fans);
        }
    }

    /**
     * 通知所有的观察者
     */
    public abstract void notifyFans(String msg);

}

/**
 * 具体的观察者:电影粉丝
 */
public class MovieFans implements Fans{

    private String name;

    public MovieFans(){

    }

    public MovieFans(String name){
        this.name = name;
    }

    @Override
    public void notify(String msg) {
        System.out.println(name+msg);
    }
}

/**
 * 具体主题
 */
public class MovieStar extends Star{
    @Override
    public void notifyFans(String msg) {
        if (!list.isEmpty()){
            list.forEach(fans ->fans.notify(msg));
        }
    }
}

/**
 * 具体观察者:音乐粉丝
 */
public class MusicFans implements Fans{

    @Override
    public void notify(String msg) {
        System.out.println(msg);
    }
}

/**
 *具体主题:音乐明星
 */
public class MusicStar extends Star{
    @Override
    public void notifyFans(String msg) {
        if (!list.isEmpty()){
            list.forEach(fans -> fans.notify(msg));
        }
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {

        //创建一个电影明星
        MovieStar movieStar = new MovieStar();
        //创建两个电影粉丝
        MovieFans movieFans1 = new MovieFans("张三");
        MovieFans movieFans2 = new MovieFans("李四");
        //两粉丝关注明星
        movieStar.addFans(movieFans1);
        movieStar.addFans(movieFans2);

        movieStar.notifyFans("电影即将上映!");
        //取消关注
        movieStar.removeFans(movieFans1);
        movieStar.notifyFans("感谢粉丝支持!");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值