前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初识设计模式

初识设计模式

作者头像
云边小卖部
发布2022-12-02 10:07:35
1560
发布2022-12-02 10:07:35
举报
文章被收录于专栏:技术分享1技术分享1

单例模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例,即只提供一个取得其对象的方法

  • 定义:只需要三步就可以保证对象的唯一性
    • (1) 不允许其他程序用new对象
    • (2) 在该类中创建对象
    • (3) 对外提供一个可以让其他程序获取该对象的方法

懒汉模式:

使用懒汉式,只有当程序需要new一个实例的时候,他才会去创建一个实例,

代码语言:javascript
复制
public class LazyMan {
private LazyMan() {
 }

private static LazyMan lazyMan;

/**
        * 线程不安全
     * @return
     */
    public static LazyMan getInstance() {
    if (lazyMan==null){
        lazyMan=new LazyMan();
    }
    return lazyMan;
    }

    /**
     * 双重校验锁
     * @return
     */
    public static LazyMan getInstanceTwo(){
        if(lazyMan==null){
            synchronized (LazyMan.class){
                if (lazyMan==null){
                    lazyMan=new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}

饿汉模式:

顾名思义,他是一个饿汉,他很勤快就怕自己饿着。他总是先把食物准备好,什么时候需要吃了,他随时拿来吃,不需要临时去搞食物。 即饿汉式在一开始类加载的时候就已经实例化,并且创建单例对象,以后只管用即可。 代码实现

代码语言:javascript
复制
/**
 * 单例模式中的饿汉式
 * 单例模式的饿汉式[可用]
 * (1)私有化该类的构造函数
 * (2)通过new在本类中创建一个本类对象
 * (3)定义一个公有的方法,将在该类中所创建的对象返回
 * <p>
 * 优点:从它的实现中我们可以看到,这种方式的实现比较简单,在类加载的时候就完成了实例化,避免了线程的同步问题。
 * 缺点:由于在类加载的时候就实例化了,所以没有达到Lazy Loading(懒加载)的效果,也就是说可能我没有用到这个实例,但是它
 * 也会加载,会造成内存的浪费(但是这个浪费可以忽略,所以这种方式也是推荐使用的)。
 *
 * @Author sunjl
 * @Date 2022/7/11 16:23
 * @Version 1.0.0
 */
public class EvilMan {
    private EvilMan() {
    }

    private static EvilMan evilMan = new EvilMan();

    public static EvilMan getInstace() {
        return evilMan;
    }
    /**
     * 2. 单例模式的饿汉式变换写法[可用]
     * 基本没区别
     */
    private static EvilMan evilManTwo=null;
    
    static {
        evilMan=new EvilMan();
    }
    public static EvilMan getInstanceTwo(){
        if (evilMan==null){
            evilMan=new EvilMan();
        }
        return evilManTwo;
    }
}

懒汉式和饿汉式的安全和性能区别:

(1) 线程安全:饿汉式在线程还没出现之前就已经实例化了,所以饿汉式一定是线程安全的。懒汉式加载是在使用时才会去new 实例的,那么你去new的时候是一个动态的过程,是放到方法中实现的,比如:

代码语言:javascript
复制
public static synchronized Singleton getInstance(){
          if(instance == null){
     //什么时候用就什么时候new
              instance = new Singleton();
          }
}
java

如果这个时候有多个线程访问这个实例,这个时候实例还不存在,还在new,就会进入到方法中,有多少线程就会new出多少个实例。一个方法只能return一个实例,那最终return出哪个呢?是不是会覆盖很多new的实例?这种情况当然也可以解决,那就是加同步锁,避免这种情况发生 。

(2)执行效率:饿汉式没有加任何的锁,因此执行效率比较高。懒汉式一般使用都会加同步锁,效率比饿汉式差。 (3)内存使用:饿汉式在一开始类加载的时候就实例化,无论使用与否,都会实例化,所以会占据空间,浪费内存。懒汉式什么时候用就什么时候实例化,不浪费内存。

参考链接:https://blog.csdn.net/m0_60092917/article/details/118718889

工厂模式

静态工厂模式

项目中的辅助类,如HttpUtils.doGet()等,使用方式类+静态方法。

简单工厂模式

​ 专门定义一个类来负责创建其他类的实例,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。(被创建的实例通常都具有共同的父类)

代码实现:

代码语言:javascript
复制
/**
 * 简单工厂模式实现
 *
 * @Author sunjl
 * @Date 2022/7/12 15:05
 * @Version 1.0.0
 */
public class SimpleRoujiaMoFactory {
    abstract class SJL {
    }

    public class SJL1 extends SJL {
        public SJL1() {
            System.out.println("创建实例1");
        }
    }

    public class SJL2 extends SJL {
        public SJL2() {
            System.out.println("创建实例 2");
        }
    }

    public class SJL3 extends SJL {
        public SJL3() {
            System.out.println("创建实例 3");
        }
    }


    public SJL creatFactory(int type) {
        SJL sjl = null;
        switch (type) {
            case 1:
                sjl = new SJL1();
                break;
            case 2:
                sjl = new SJL2();
                break;
            case 3:
                sjl=new SJL3();
                break;
        }
        return sjl;
    }
}
java

使用工厂:

代码语言:javascript
复制
    public static void main(String[] args) {
        SimpleRoujiaMoFactory simpleRoujiaMoFactory = new SimpleRoujiaMoFactory();
        simpleRoujiaMoFactory.creatFactory(2);
    }
java

简单工厂模式的优缺点:

简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。 但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。 为了解决简单工厂模式的问题,出现了工厂方法模式

参考链接:https://blog.csdn.net/a745233700/article/details/120253639

工厂方法模式

​ 工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每 实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。

实现代码:

创建抽象工厂实现方法

代码语言:javascript
复制
/**
 * 抽象创建工厂
 * 注意,我们在这里采用了泛型(Generic),通过定义泛型对createHuman的输入参数产
 * 生两层限制:
 * ● 必须是Class类型;
 * ● 必须是Human的实现类
 *
 * @Author sunjl
 * @Date 2022/7/12 19:16
 * @Version 1.0.0
 */

public abstract class AbstractHumanFactory {
    public abstract <T extends Human> T creatHuman(Class<T> c);
}
java

实现方法

代码语言:javascript
复制
/**
 * 创建工厂
 *
 * @Author sunjl
 * @Date 2022/7/12 19:21
 * @Version 1.0.0
 */
public class HumanFactory extends AbstractHumanFactory {
    @Override
    public <T extends Human> T creatHuman(Class<T> c) {
        Human human = null;
        //通过newInstance创建新的类的实例
        try {
            human = (T) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) human;
    }
}
java

创建产品

代码语言:javascript
复制
/**
 * 实现方法
 *
 * @Author sunjl
 * @Date 2022/7/12 19:40
 * @Version 1.0.0
 */
public class NvWa {
    public static void main(String[] args) {
        HumanFactory humanFactory = new HumanFactory();
        BlackHuman blackHuman = humanFactory.creatHuman(BlackHuman.class);
        blackHuman.getColor();
        blackHuman.talk();
    }
}
java
代码语言:javascript
复制
/**
 * 实现逻辑方法
 *
 * @Author sunjl
 * @Date 2022/7/12 19:04
 * @Version 1.0.0
 */
public class BlackHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("一个黑人");
    }

    @Override
    public void talk() {
        System.out.println("黑人之话,");
    }
}
java
代码语言:javascript
复制
/**
 * 可理解为产品方法,逻辑方法判断
 *
 * @Author sunjl
 * @Date 2022/7/12 19:02
 * @Version 1.0.0
 */
public interface Human {
    void getColor();
    void talk();
}
java

建造者模式

当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。

主要用的地方是在实体类的链式编程中使用,

● Product产品类 通常是实现了模板方法模式,也就是有模板方法和基本方法,这个参考第10章的模板方 法模式。例子中的BenzModel和BMWModel就属于产品类。

● Builder抽象建造者 规范产品的组建,一般是由子类实现。例子中的CarBuilder就属于抽象建造者。

● ConcreteBuilder具体建造者 实现抽象类定义的所有方法,并且返回一个组建好的对象。例子中的BenzBuilder和 BMWBuilder就属于具体建造者。

● Director导演类 负责安排已有模块的顺序,然后告诉Builder开始建造,在上面的例子中就是我们的老 大,××公司找到老大,说我要这个或那个类型的车辆模型,然后老大就把命令传递给我,我 和我的团队就开始拼命地建造,于是一个项目建设完毕了。

代理模式

代理模式(Proxy Pattern)是一个使用率非常高的模式,其定义如下: Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供 一种代理以控制对这个对象的访问。)

代理模式的优点 :

● 职责清晰 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理 完成一件事务,附带的结果就是编程简洁清晰。

● 高扩展性 具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱 如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

● 智能化 这在我们以上的讲解中还没有体现出来,不过在我们以下的动态代理章节中你就会看到 代理的智能化有兴趣的读者也可以看看Struts是如何把表单元素映射到对象上的

AOP框架时,弄清楚几个名词就成:切面(Aspect)、切入点 (JoinPoint)、通知(Advice)、织入(Weave)就足够了,理解了这几个名词,应用时你 就可以游刃有余了!

AOP动态代理模式

三种获取Class的对象的方法

1.反射。用到了Class类中的静态方法forName(String className).传入的字符串参数是类的全路径名。因为可以传入字符串,所以这种方法也可以用到配置文件中,使其修改路径更加方便。

代码语言:javascript
复制
	@SuppressWarnings("rawtypes")
	Class cls = Class.forName("java.lang.String");
	System.out.println(cls);
java

2.通过类的实例对象调用getClass()方法,这个方法是继承Object类得来的。

代码语言:javascript
复制
		String str = "csdn";
		Class cls2 = str.getClass();
		System.out.println(cls2); 
java

3.根据类名直接获取对应的Class的对象 : 类名.class

代码语言:javascript
复制
		Class cls1 = String.class;
		System.out.println(cls1);
java

加上this关键字,我就是要调用本类中的成员变量或方法,而不是本方 法中的一个变量。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式
    • 懒汉模式:
      • 饿汉模式:
        • 懒汉式和饿汉式的安全和性能区别:
        • 工厂模式
          • 静态工厂模式
            • 简单工厂模式
              • 简单工厂模式的优缺点:
            • 工厂方法模式
            • 建造者模式
            • 代理模式
              • 代理模式的优点 :
                • AOP动态代理模式
                • 三种获取Class的对象的方法
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档