设计模式学习笔记

迭代器模式

迭代器模式应该是所有的设计模式中,应用程度最广的一个,广到Java本身就已经对绝大多数的集合类支持了这个这种设计模式,也就是在开发过程中常见的迭代器(Iterator)

UML

img

主要角色

迭代器接口

public interface Iterator{
    object first();
    object next();
    boolean isDone();
    object currentItem();
}

迭代器接口声明了迭代器的四个主要功能,分别是:

  1. 将指标移动到第一个位置
  2. 将指标移动到下一个位置
  3. 判断是否已经遍历完成
  4. 获取当前坐标下的值

Aggregate 抽象类

public abstract class Aggregate{
    public abstract Iterator createIterator();
}

声明了创建构造器的抽象方法

迭代器接口的实现类

public class ClassroomIterator implements Iterator{
    private List<Object> list = new ArrayList<Object>();
    private int offset = 0;
    public ClassroomIterator(List<Object> list){
        this.list = list;
    }

    public object first(){
        return list.get(0);
    }
    
    public object next(){
        object result = null;
        offset++;
        if(offset > list.size()){
            result = list.get(offset);
        }
        return result;
    }
    
    public boolean isDone(){
        return offset < list.size();
    }
    
    public object currentItem(){
        return list.get(offset);
    }
    
}

内部包含两个变量list和offset,通过传入list的方式进行初始化。实现迭代器接口相关方法。

Aggregate实现类

public Classroom extends Aggregate{
    private List<object> list = new ArrayList<object>();
    
    public ConcreateAggregate ( List<object> list){
        this.list = list;
    }
    
    public Iterator createIterator(){
        return new ClassroomIterator(this);
    }
}

client

Student s1 = new Student("leo");
Student s2 = new Student("mary");
List<Student> list = new ArrayList<>(){{add(s1);add(s2);}};
Classroom cr = new Classroom(list);
Iterator iterator = cr.createIterator();
while(iterator.isDone){
    System.out.println(iterator.next)
}

应用场景

比如说现在有四个人再做开发,前三个人每个人对应维护一张数据表,最后一个人需要对这些数据进行汇总查询,但是前面的三个人的返回数据结构分别是list、set、数组。

在这种情况下,我们就可以考虑迭代器模式。大家都返回的是迭代器,然后客户端使用迭代起对其进行遍历获取数据

适配器模式

应用场景

适配器模式也是开发中常用的一种设计模式,通常出现在比如公司有严格的接口规范,比如存储必须以save开头,获取单个结果必须是get开头,获取list必须是list开头等等。但是往往第三方的接口不会匹配这样的规则,比如说redis等等。这个时候就特别适合使用适配器模式

UML

img

主要角色

老接口

public interface OldInterface{
    void doSomething();
}

新接口

public interface NewInterface{
    void doSomething();
}

适配器

public class AdapterParttern implements NewInterface{
    
    private OldInterface oldInterface;
    
    public AdapterParttern(OldInterface old){
        this.oldInterface = old;
    }
    
    public void doSomething(){
        oldInterface.doSomething();
    }
    
}

模板模式

应用场景,避免重复代码

UML

img

主要角色

模板

public abstract class MorningTemplate{
    
    protected void do(){
        getUp();
        washingFace();
        eat();
    }
    
    public abstract void getUp();
    
    public abstract void washingFace();
    
    public abstract void eat();
    
}

实现

public class JasonMorning extends MorningTemplate{
    
    public void getUp(){
        System.out.println("getUp");
    }
    
    public void washingFace(){
        System.out.println("washing face");
    }

    public void eat(){
        System.out.println("eat");
    }
    
}

客户端

public class client{
    
    public static void main(String[] args){
        MorningTemplate jason = new JasonMorning();
        jason.do();
    }
    
}

工厂模式

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。工厂模式简单来说可以分为三类:

  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式

简单工厂模式

interface Product{
    void make();
}

class SpecialProduct implements Product{
    
    @Override
    public void make(){
        System.out.println("make a special product。。")
    }
}

class ProductFactory(){
    public Product createProduct(){
        return new SpecialProduct();
    }
}

class client{
    public static void main(String[] args){
        Product product = ProductFactory.createProduct();
        product.make();
    }
}

工厂方法模式

interface Product{
    void make();
}

class SpecialProduct implements Product{
    public SpecialProduct(){
        System.out.println("create special product");
    }
    
    @Override
    public void make(){
        System.out.println("make a special product")
    }
}

interface ProductFactory{
    Product create();
}

class SpecialProductFactory implements ProductFactory{
    
    private static final SpecialProductFactory INSTANCE = new SpecialProductFactory();
    private SpecialProductFactory(){};
    
    public static SpecialProductFactory getInstance(){
        return INSTANCE;
    }
    
    @Override
    public Product create(){
        return new SpecialProduct();
    }
}

public class ClientDemo{
    public static void main(String[] args){
        Product product = SpecialProductFactory.getInstance.create();
        product.make();
    }
}

抽象工厂模式

单例模式

单例模式比较简单,这里就不声明角色和UML图了。直接看代码吧

饿汉模式

public class Singleton{
    private static final Singleton INSTANCE = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

线程不安全的懒汉模式

public class Singleton{
    private static Singleton instance;
    private Singletion(){}
    public static Singleton getInstance(){
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

双重检查锁的懒汉模式

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

内部类模式

public class Singleton{
    private static Singleton instance;
    private Singletion(){}
    private static class SingletonHolder{
        private static final INSTANCE = new Singleton();
    }
    public static Singleton getInstance(){
        return SingletonHolder.INSTACE;
    }
}

枚举类模式

public enum AddressEnumSingleton {
    INSTANCE;
    private static String ip;

    static {
        System.out.println("执行静态块");
        try {
            ip = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    AddressEnumSingleton() {
        System.out.println("创建单例模式");
    }
    public static String getIp() {
        System.out.println("获取ip地址 : " + ip);
        return ip;
    }
}
// 调用
public static void main(String[] args) {
	AddressEnumSingleton.getIp();  
}

构造器模式

UML

img

package com.zhss.designpattern.builder;

public class OptimizedBuilderPatternDemo {
	
	public static void main(String[] args) {
		Product product = new ConcreteBuilder()
				.field1("值1")
				.field2("值2")
				.field3("值3")
				.create();
		System.out.println(product);  
		
		// 现在基本上流行的一些开源框架,构造器模式的运用,一般都是上面这种变种模式
	}
	
	public static class Product {
		
		private String field1;
		private String field2;
		private String field3;
		
		public String getField1() {
			return field1;
		}
		public void setField1(String field1) {
			this.field1 = field1;
		}
		public String getField2() {
			return field2;
		}
		public void setField2(String field2) {
			this.field2 = field2;
		}
		public String getField3() {
			return field3;
		}
		public void setField3(String field3) {
			this.field3 = field3;
		}
		
		@Override
		public String toString() {
			return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
		}
		
	}
	
	public interface Builder {
		
		Builder field1(String value);
		Builder field2(String value);
		Builder field3(String value);
		Product create();
		
	}
	
	public static class ConcreteBuilder implements Builder {

		private Product product = new Product();
		
		public Builder field1(String value) {
			System.out.println("在设置field1之前进行复杂的校验逻辑");  
			product.setField1(value); 
			return this;
		}
		
		public Builder field2(String value) {
			System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");  
			product.setField2(value);
			return this;
		}

		public Builder field3(String value) {
			System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
			product.setField3(value);  
			return this;
		}
		
		public Product create() {
			return product;
		}
		
	}
	
}

门面模式

这个门面模式,其实代码中很常见。就是把多个方法封装在一个方法内提供出去。在隆众的项目中。这种设计模式被大量的使用。因为我们对外提供的接口都是这种模式。比如informationFacade、channelFacade等等。

闲话少叙,直接看代码吧。

package com.zhss.designpattern.facade;

public class FacadePatternDemo {
	
	public static void main(String[] args) {
		// 假设是子系统2
		SystemFacade facade = new SystemFacade();
		facade.exucute();
		
		// 好处1:子系统2不需要care太多的模块,只要care一个门面类的接口就可以了
		// 好处2:如果多个地方都要调用这段逻辑,那么如果这个逻辑变了,只需要在门面类一个地方修改就可以了
	}
	
	/**
	 * 子系统1的门面类
	 * @author zhonghuashishan
	 *
	 */
	public static class SystemFacade {
		
		public void exucute() {
			// 子系统1,封装了自己的多个模块,ABC,基于自己多个模块的功能,对外统一暴露出去一个功能
			ModuleA moduleA = new ModuleA();
			ModuleB moduleB = new ModuleB();
			ModuleC moduleC = new ModuleC();
			
			moduleA.execute();
			moduleB.execute();
			moduleC.execute();
			System.out.println("新增的一段逻辑");
		}
		
	}
	
	public static class ModuleA {
		
		public void execute() {
			System.out.println("子系统1的模块A的功能");
		}
		
	}
	
	public static class ModuleB {
		
		public void execute() {
			System.out.println("子系统1的模块B的功能");
		}
		
	}
	
	public static class ModuleC {
		
		public void execute() {
			System.out.println("子系统1的模块C的功能");
		}
		
	}
	
}

原型模式

UML

img

主要角色

客户(Client)角色客户类提出创建对象的请求;

抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或者Java抽象类实现。此角色定义了的具体原型类所需的实现的方法。

具体原型(Concrete Prototype)角色:此角色需要实现抽象原型角色要求的克隆相关接口

/**
 * 抽象原型角色
 */
public abstract class Prototype {
    private String id;

    public Prototype(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    /**
     * 克隆自身的方法
     * @return 一个从自身克隆出来的对象。
     */
    public abstract Prototype clone();
}


public class ConcretePrototype1 extends Prototype {
    public ConcretePrototype1(String id) {
        super(id);
    }

    public Prototype clone() {
        Prototype prototype = new ConcretePrototype1(this.getId());
        return prototype;
    }
}


public class ConcretePrototype2 extends Prototype {
    public ConcretePrototype2(String id) {
        super(id);
    }

    public Prototype clone() {
        Prototype prototype = new ConcretePrototype2(this.getId());
        return prototype;
    }
}


深拷贝:

​ 如果修改B对象的属性和方法不会影响A对象的属性和方法,这是深拷贝。简单来说一个对象引用了另外一个对象,如果对另外一个对象进行了修改。拷贝出来的属性不会被修改。

img

浅拷贝:

如果修改B对象的属性和方法会印象A对象的属性和方法,这是浅拷贝。articleDTO中有一个属性是articleContentDTO,拷贝之后如果再次修改源articleContentDTO的值,拷贝出来的结果也会发生变更。

img

中介者模式

代理模式

静态代理

package com.zhss.designpattern.proxy;

/**
 * @description: 静态代理模式
 * @projectName: designpattern
 * @see: com.zhss.designpattern.Proxy
 * @author: 祁琦
 * @createTime: 2020/1/14 13:49
 * @version: 1.0
 */
public class StaticProxyPattern {

    public static void main(String[] args) {
        Star jay = new Jay();
        Star proxy = new ProxyStar(jay);
        proxy.sing();
    }

    public interface Star {
        void sing();
    }

    public static class Jay implements Star {

        @Override
        public void sing() {
            System.out.println("周杰伦正在唱歌");
        }
    }

    public static class ProxyStar implements Star {

        private Star star;

        public ProxyStar(Star star) {
            this.star = star;
        }

        @Override
        public void sing() {
            System.out.println("唱歌之前的准备工作");
            star.sing();
            System.out.println("休息休息一下");
        }
    }

}


/* system out */
/*
唱歌之前的准备工作
周杰伦正在唱歌
休息休息一下
*/

JDK 动态代理

动态代理的主要特点就是能够在程序运行时JVM才为被代理对象生成代理对象。

常说的动态代理也叫做JDK代理也是一种接口代理,JDK中生成代理对象的代理类就是Proxy,所在包是java.lang.reflect

package com.zhss.designpattern.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @description: jdk动态代理模式
 * @projectName: designpattern
 * @see: com.zhss.designpattern.proxy
 * @author: 祁琦
 * @createTime: 2020/1/14 13:56
 * @version: 1.0
 */
public class JdkProxyPattern {

    public interface Dog {
        void run();
    }

    public static class MyDog implements Dog {
        @Override
        public void run() {
            System.out.println("小狗快跑");
        }
    }

    public static class MyInvocationHandle implements InvocationHandler {
        private Dog dog;

        public MyInvocationHandle(Dog dog) {
            this.dog = dog;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("准备跑");
            method.invoke(dog, args);
            System.out.println("跑完了");
            return null;
        }
    }

    public static class ProxyDogFactory {
        public static Object getProxyDog(Dog dog) {
            MyInvocationHandle myInvocationHandle = new MyInvocationHandle(dog);
            return Proxy.newProxyInstance(dog.getClass().getClassLoader(), dog.getClass().getInterfaces(), myInvocationHandle);
        }
    }

    public static void main(String[] args) {
        MyDog myDog = new MyDog();
        Dog proxyDog = (Dog) ProxyDogFactory.getProxyDog(myDog);
        proxyDog.run();
    }

}

代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能使用动态代理,因此这也算是这种方式的缺陷。

cglib 动态代理

上面的静态代理和动态代理模式有个相同点就是都要求目标对象是实现一个接口的对象,然而并不是任何对象都会实现一个接口,也存在没有实现任何的接口的对象,

这时就可以使用继承目标类以目标对象子类的方式实现代理,这种方法就叫做:Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.

使用JDK动态代理有一个限制,就是被代理的对象必须实现一个或多个接口,若想代理没有实现接口的类,就需要使用Cglib实现.

package com.zhss.designpattern.proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
* @description: CGlib代理模式
* @projectName: designpattern
* @see: com.zhss.designpattern.proxy
* @author: 祁琦
* @createTime: 2020/1/14 14:21
* @version: 1.0
*/
public class CglibProxyPattern {

   public static class UserServiceImpl {
       public void add() {
           System.out.println("添加用户");
       }
   }

   public static class UserServiceProxy implements MethodInterceptor {
       private UserServiceImpl userService;

       public Object getInstance(UserServiceImpl userService) {
           this.userService = userService;
           Enhancer enhancer = new Enhancer();
           enhancer.setSuperclass(this.userService.getClass());
           enhancer.setCallback(this);
           return enhancer.create();
       }
       @Override
       public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
           System.out.println("开始事务处理机制");
           Object invokeSuper = methodProxy.invokeSuper(o, objects);
           System.out.println("提交事务");
           return invokeSuper;
       }
   }

   public static void main(String[] args) {
       UserServiceProxy serviceProxy = new UserServiceProxy();
       UserServiceImpl instance = (UserServiceImpl) serviceProxy.getInstance(new UserServiceImpl());
       instance.add();
   }

}

观察者模式

原文地址:https://www.cnblogs.com/joimages/p/12192246.html