设计模式

1.单例模式
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
单例模式有 3 个特点:
单例类只有一个实例对象;
该单例对象必须由单例类自行创建;
单例类对外提供一个访问该单例的全局访问点;
单例模式有两种类型:
懒汉式:在真正需要使用对象时才去创建该单例类对象
饿汉式:在类加载时已经创建好该单例对象,等待被程序使用

懒汉式
public class Singleton {
private static Singleton singleton;
private Singleton(){} //将类的构造函数私有化,这样可以防止类的外部创建实例,
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}

饿汉式
饿汉式在类加载时已经创建好该对象,在程序调用时直接返回该单例对象即可,即我们在编码时就已经指明了要马上创建这个对象,不需要等到被调用时再去创建。关于类加载,涉及到JVM的内容,我们目前可以简单认为在程序启动时,这个单例对象就已经创建好了
public class SingletonTest02 {
public static void main(String[] args) {
//测试
Singleton instance = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance == instance2); // true
System.out.println("instance.hashCode=" + instance.hashCode());
System.out.println("instance2.hashCode=" + instance2.hashCode());
}
}
//饿汉式(静态变量)

public class Singleton
{
// 自行预先实例化,内部定义自己唯一实例,只供内部使用 //
private static Singleton Instance = new Singleton();

private Singleton()
{

}
// 提供外部访问的静态方法,来对内部唯一实例进行访问 //
public static Singleton GetInstance()
{
return Instance;
}
}

双重检查锁单例模式(解决线程安全)
public class Singleton{
private static final Singleton singleton = new Singleton();
private Singleton(){} //构造器私有化
public static Singleton getInstance() {
return singleton;
}
}
这个方法其实是存在问题的,试想一下,如果两个线程同时判断singleton为空,那么它们都会去实例化一个Singleton对象,这就变成双例了。所以,我们要解决的是线程安全问题。
所以需要加锁
public class Singleton {
private static Singleton singleton;
private Singleton(){} //私有化构造器,防止外部创建实例
public static Singleton getInstance() {
if (singleton == null) {
synchronized(Singleton.class) { // 线程A或线程B获得该锁进行初始化
if (singleton == null) { // 其中一个线程进入该分支,另外一个线程则不会进入该分支
singleton = new Singleton();
}
}
}
return singleton;
}
}
总结
(1)单例模式常见的写法有两种:懒汉式、饿汉式
(2)懒汉式:在需要用到对象时才实例化对象,正确的实现方式是:Double Check + Lock,解决了并发安全和性能低下问题
(3)饿汉式:在类加载时已经创建好该单例对象,在获取单例对象时直接返回对象即可,不会存在并发安全和性能问题。
(4)在开发中如果对内存要求非常高,那么使用懒汉式写法,可以在特定时候才创建该对象;
(5)如果对内存要求不高使用饿汉式写法,因为简单不易出错,且没有任何并发安全和性能问题
(6)为了防止多线程环境下,因为指令重排序导致变量报NPE,需要在单例对象上添加volatile关键字防止指令重排序
(7)最优雅的实现方式是使用枚举,其代码精简,没有线程安全问题,且 Enum 类内部防止反射和反序列化时破坏单例
https://blog.csdn.net/weixin_41949328/article/details/107296517?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166658337916782417030437%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166658337916782417030437&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107296517-null-null.142^v59^pc_rank_34_queryrelevant25,201^v3^control_1&utm_term=%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187

2.简单工厂模式:(静态工厂方法模式)
简单工厂模式属于类创建型模式
可以根据参数的不同返回不同的实例
专门创建一个类来创建其他类的实例(new实例都交给工厂)
被创建的实例通常具有共同的父类

简单工厂中的角色:
1. 抽象产品类
2. 产品子类
3. 工厂类

abstract class Product{
public void use() {

}
}

class ProductA extends Product {
public void use(){
System.out.println("使用了产品A");
}
}

class ProductB extends Product {
public void use(){
System.out.println("使用了产品B");
}
}

class Factory{
public static Product createProduct(String type){
if (type.equals("A")){
return new ProductA();
}else if (type.equals("B")) {
return new ProductB();
}
return new ProductA();
}
}
*/
就相当于工厂造衣服裤子,简单工厂模式就是中间人,你要买衣服还是裤子,由它来给你new
简单工厂模式,利用静态方法根据输入参数生成对应的产品,隐藏了产品实例化的细节。
简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是当需求变动的时候,需要对原有的类进行修改,违背了开放封闭原则。
3.工厂模式
开闭原则:程序对于扩展是开放的,但对于修改是封闭的
原来核心简单工厂变成了一个抽象接口,①负责给出工厂应该实现的方法,不在负责产品的创建,②把创建产品的工作交给子类去做,就有了子工厂,即子类,负责生产具体的产品对象。这样做可以将产品类实例化工作延迟到子类中进行,即通过工厂子类来确定究竟应该实例化哪一个具体实现类
在工厂模式下,每新增一个产品,都会新增一个与之对应工厂类,属于是1对1的额,即每一个具体工厂都对应生产一种具体产品,并且所有这些产品都继承于同一抽象类或实现了同一接口
当需要增加一个新产品ProductD,只需要新建对应的FactoryD来实现生产功能即可,对原有的代码没有任何影响,非常符合开放封闭原则,但是由于每增加一个产品,都需要新增对应的生产工厂,导致增加额外的开发工作量。

//首先声明一个工厂接口,所有工厂必须实现这个接口
public interface IFactory {
Product createProduct();
}
//生产ProductA的工厂FactoryA
public class FactoryA implements IFactory {
@Override
public Product createProduct() {
return new ProductA();
}
}
//生产ProductB的工厂FactoryB
public class FactoryB implements IFactory {
@Override
public Product createProduct() {
return new ProductB();
}
}
//同样地,生产ProductC的工厂FactoryC跟以上模式一样。
//现在来根据新的工厂方法模式来生产
IFactory factoryA = new FactoryA();
Product productA = factoryA.createProduct();
System.out.println("productA name="+productA.getName()+",getPrice:"+productA.getPrice());

IFactory factoryB = new FactoryB();
Product productB = factoryB.createProduct();
System.out.println("productB name="+productB.getName()+",getPrice:"+productB.getPrice());


IFactory factoryC = new FactoryB();
Product productC = factoryC.createProduct();
System.out.println("productC name="+productC.getName()+",getPrice:"+productC.getPrice());

4.抽象工厂
https://www.cnblogs.com/heliusKing/p/11577837.html
假设现在需要针对每种产品生产对应的赠品,难道我们要新增一个Gift的生产工厂吗?其实没有必要,因为在这个场景下,每种产品必须附带了赠品,所以我们可以利用原有的工厂来生产赠品。
姜富春理解:就是在工厂模式的工厂中把”抽象“方法加进去,但得修改接口
//先定一个共同的Gift接口
public interface Gift {
String getGiftName();
}
//增加GiftA、GiftB、GiftC
public class GiftA implements Gift {
@Override
public String getGiftName() {
return "GiftA";
}
}
//修改Factory接口,增加生产Gift的方法
public interface IFactory {
Product createProduct();
Gift createGift();
}
//修改工厂方法模式下的FactoryA、FactoryB、FactoryC
public class FactoryA implements IFactory {
@Override
public Gift createGift() {
return new GiftA();
}

@Override
public Product createProduct() {
return new ProductA();
}
}
//生产产品和赠品
IFactory factoryA = new FactoryA();
Product productA = factoryA.createProduct();
Gift giftA = factoryA.createGift();
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。抽象工厂接口,应该包含所有的产品创建的抽象方法,我们可以定义实现不止一个接口,一个工厂也可以生产不止一种产品类,和工厂方法模式一样,抽象工厂模式同样实现了开发封闭原则

4.装饰器模式
定义:动态的给一个对象添加一些额外的功能。
比如一个机器人有扫地的功能,但我想让它跳舞,于是和商家反馈,商家说下一代机器人将会有跳舞功能,这时候小黑说它可以直接在一代机器人身上添加跳舞功能,于是它给机器人套了一个壳,在壳上装了两条腿,这就能跳舞了,这就是装饰器模式
装饰器模式是在原有类的基础上动态添加新的功能,这种添加功能的方式不同于继承,它是在对象层面实现功能扩展,而不是继承的类层面,因此说装饰器模式比继承更加灵活。另外,装饰器模式属于结构型设计模式。之前讲的都是创建型设计模式。创建型可以理解为生成新的对象,而结构型可以理解为构建更大的类或类对象。

5.适配器模式
定义: 将一个类的接口变换成客户端所期待的另一个接口,从而使原本因接口不匹配而无法在一起工作的两个类能在一起工作
装饰器模式是指给一个类增强一些方法,对其做一些包装,但是不会影响改变原本类。
举例:新闻联播手语老师的小窗口

6.观察者模式
定义:对象间的一种一对多依赖关系,使得每一个对象状态发生改变时,其相关依赖对象都会得到通知并且自动更新

7.迭代器是一种行为设计模式让你能在不暴露集合底层表现形式(列表,栈和树等)的情况下遍历集合中所有的元素

posted on 2023-05-17 20:29  Red_kucha  阅读(22)  评论(0)    收藏  举报

导航