设计模式

分享 123456789987654321 ⋅ 于 2022-08-23 08:36:54 ⋅ 1256 阅读

设计模式

1.创建型模式

1.单例模式

//双重检查锁+内存可见性(设计模式) ->懒汉式线程安全

package com.atguigu.design.creatation.singleton;

/**
 * 单例模式 
 * 双重检查锁+内存可见性(设计模式)
 */
public class Person {
    private String name;
    private String age;

    //懒汉、饿汉
    private volatile static Person instance;  //饿汉
    //private volatile static Person instance1 = new Person();  //懒汉

    //构造器私有,外部不能实例化
    private Person() {
        System.out.println("创建了Person");
    }

    //提供给外部的方法
    //1、public static synchronized Person guiguBoss() 锁太大
    //2、双重检查锁+内存可见性(设计模式)
    public static Person guiguBoss() {
        //如果没有再去创建
        if (instance == null) {
            synchronized (Person.class) {
                if(instance == null){ //如果这里不判断,则多线程会出现问题
                    Person person = new Person();
                    //多线程问题
                    instance = person;
                }
            }
        }
        return instance;
    }
}

----------------------------------------------------------------------------------------------
//测试代码
import java.util.Map;
import java.util.Properties;

public class MainTest {

    public static void main(String[] args) {
//        Person person1 = Person.guiguBoss();
//        Person person2 = Person.guiguBoss();
//        System.out.println(person1 == person2);
//        Properties properties = System.getProperties();
//        System.out.println(properties);

        //获取当前系统的环境变量
        Map<String, String> getenv = System.getenv();
        System.out.println(getenv);
    }
}

--------------------------
//单例模式应用场景
数据库连接池,  线程池,   系统环境信息,     上下文    

2.原型模式

本体拷贝一个克隆体 一个对象多个修改者的场景

深克隆/浅克隆

//对象 implements Cloneable

/**
 * 是用于创建重复的对象,同时又能保证性能。
 * 1、GuiguMyBatis:操作数据库,从数据库里面查出很多记录(70%改变很少)
 * 2、每次查数据库,查到以后把所有数据都封装一个对象,返回。
 *    10000 thread:查一个记录: new User("zhangsan",18);每次创建一个对象封装并返回
 *    系统里面就会有10000个User;浪费内存
 * 3、解决:缓存;查过的保存。
 *          如果再查相同的记录,拿到原来的原型对象
 *
 * 4、此时直接拿到缓存中的对象。
 *
 *
 */
public class MainTest {

    public static void main(String[] args) throws Exception {
        GuiguMybatis mybatis = new GuiguMybatis();

        //十分危险
        //得到的是克隆体
        User zhangsan1 = mybatis.getUser("zhangsan");
        System.out.println("1==>"+zhangsan1);
        zhangsan1.setUsername("李四2.。。");
        System.out.println("zhangsan1自己改了:"+zhangsan1);

        //得到的是克隆体
        User zhangsan2 = mybatis.getUser("zhangsan");
        System.out.println("2-->"+zhangsan2);

        //得到的是克隆体
        User zhangsan3 = mybatis.getUser("zhangsan");
        System.out.println("3-->"+zhangsan3);

        //得到的是克隆体
        User zhangsan4 = mybatis.getUser("zhangsan");
        System.out.println("4-->"+zhangsan4);

        System.out.println(zhangsan1 == zhangsan3);

    }
}
package com.atguigu.design.creatation.prototype;

/**
 * 当前对象是可克隆的
 */
public class User implements Cloneable {

    private String username;
    private Integer age;

    public User(){
        System.out.println("User对象创建");
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }

    /**
     * 再创建一个人,赋予我的所有属性
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = new User();
        user.setUsername(username);
        user.setAge(age);
        return user;
    }
}
package com.atguigu.design.creatation.prototype;

import java.util.HashMap;
import java.util.Map;

public class GuiguMybatis {

    //缓存user.序列化和反序列化-深克隆
    private Map<String,User> userCache = new HashMap<>();

    /**
     * 从数据库查数据
     * @return
     */
    public User getUser(String username) throws Exception {
        User user = null;
        //缓存中没有
        if(!userCache.containsKey(username)){
            //查询数据库
            user = getUserFromDb(username);
        }else {
            //从缓存中直接拿,脏缓存问题
            //原型已经拿到,但是不能直接给。(本人)
            user = userCache.get(username);
            System.out.println("从缓存中拿到的是:"+user);
            //从这个对象快速得到一个克隆体(克隆人)==原型模式
            user = (User) user.clone();
        }

        return user;
    }

    private User getUserFromDb(String username) throws Exception{
        System.out.println("从数据库查到:"+username);
        User user = new User();
        user.setUsername(username);
        user.setAge(18);
        //给缓存中放一个clone
        userCache.put(username, (User) user.clone());
        return user;
    }
}

3.工厂模式

3.1简单工厂(不用)

AbstractCar

package com.atguigu.design.creatation.factory.simplefactory;

/**
 * 工厂的产品
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}

MainTest

package com.atguigu.design.creatation.factory.simplefactory;

public class MainTest {

    public static void main(String[] args) {

        WuLinSimpleFactory factory = new WuLinSimpleFactory();

        AbstractCar van = factory.newCar("van");
        AbstractCar mini = factory.newCar("mini");
        AbstractCar zz = factory.newCar("zz");
        van.run();
        mini.run();

    }
}

MiniCar

package com.atguigu.design.creatation.factory.simplefactory;

/**
 * 简单工厂
 */
public class MiniCar extends AbstractCar{

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}

VanCar

package com.atguigu.design.creatation.factory.simplefactory;

/**
 * 具体产品
 */
public class VanCar extends AbstractCar{

    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}

WuLinSimpleFactory

package com.atguigu.design.creatation.factory.simplefactory;

/**
 * 简单工厂
 * 1、产品数量极少
 */
public class WuLinSimpleFactory {

    /**
     *
     * @param type  Class: 好像具有扩展性,但是没有解决实际问题
     * @return
     */
    public AbstractCar newCar(String type){

        //核心方法:一切从简
        if("van".equals(type)){
            // 钣金、喷漆、放发动机、申请环保

            return new VanCar();
        }else if("mini".equals(type)){
            return new MiniCar();
        }

        //.....

        //更多的产品,违反开闭原则。应该直接扩展出一个类来造
        return null;
    }
}

3.2 工厂方法

四个角色: 抽象产品   具体产品     抽象工厂    具体工厂

AbstractCar

package com.atguigu.design.creatation.factory.factorymethod;

/**
 * 工厂的产品
 *
 * 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
 * 抽象类,接口  就会有多实现,多实现自然就有多功能
 */
public abstract class AbstractCar {

    String engine;
    public abstract void run();
}

AbstractCarFactory

package com.atguigu.design.creatation.factory.factorymethod;

/**
 * 抽象工厂的层级
 */
public abstract class AbstractCarFactory {

    public abstract AbstractCar newCar();
    //我能造口罩.....
}

MainTest

package com.atguigu.design.creatation.factory.factorymethod;

public class MainTest {

    public static void main(String[] args) {
        AbstractCarFactory carFactory = new WulinRacingCarFactory();
        AbstractCar abstractCar = carFactory.newCar();
        abstractCar.run();

        carFactory = new WulinVanCarFactory();
        AbstractCar abstractCar1 = carFactory.newCar();

        abstractCar1.run();
    }
}

MiniCar

package com.atguigu.design.creatation.factory.factorymethod;

public class MiniCar extends AbstractCar {

    public MiniCar(){
        this.engine = "四缸水平对置发动机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--> 嘟嘟嘟...");
    }
}

RacingCar

package com.atguigu.design.creatation.factory.factorymethod;

public class RacingCar extends AbstractCar{

    public RacingCar(){
        this.engine = "v8发动机";
    }
    @Override
    public void run() {
        System.out.println(engine+"=--嗖.....");
    }
}

VanCar

package com.atguigu.design.creatation.factory.factorymethod;

/**
 * 具体产品
 */
public class VanCar extends AbstractCar {
    public VanCar(){
        this.engine = "单杠柴油机";
    }

    @Override
    public void run() {
        System.out.println(engine+"--》嗒嗒嗒....");
    }
}

WulinMinCarFactory

package com.atguigu.design.creatation.factory.factorymethod;

/**
 * minicar分厂
 */
public class WulinMinCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new MiniCar();
    }
}

WulinRacingCarFactory

package com.atguigu.design.creatation.factory.factorymethod;

/**
 * RacingCar分厂
 */
public class WulinRacingCarFactory extends AbstractCarFactory{
    @Override
    public AbstractCar newCar() {
        return new RacingCar();
    }
}

WulinVanCarFactory

package com.atguigu.design.creatation.factory.factorymethod;

public class WulinVanCarFactory extends AbstractCarFactory {
    @Override
    public AbstractCar newCar() {
        return new VanCar();
    }
}

3.3抽象工厂

public abstract class WulinFactory {

    List<String> rules;

    abstract AbstractCar newCar();
    abstract AbstractMask newMask();
}
/**
 * wulin口罩集团
 * 分类 继续是 抽象类  抽象方法再由具体的子类去实现
 */
public abstract class WulinMaskFactory extends WulinFactory{
    @Override
    AbstractCar newCar() {
        return null;
    }

    abstract AbstractMask newMask();
}
/**
 * 分厂:否则口罩
 */
public class WulinWuHanMaskFactory  extends WulinMaskFactory{

    @Override
    AbstractMask newMask() {
        return new N95Mask();
    }
}

4.建造者模式/builder

Phone

//主类
package com.atguigu.design.creatation.builder;

import lombok.*;

@Data
@Builder
public class Phone {

    protected String cpu;
    protected String mem;
    protected String disk;
    protected String cam;
}

XiaomiBuilder

package com.atguigu.design.creatation.builder;

public class XiaomiBuilder  extends AbstractBuilder{

    public XiaomiBuilder(){
        //无参构造
        phone = Phone.builder().build();
    }

    @Override
    AbstractBuilder customCpu(String cpu) {
        phone.cpu = cpu;
        return this;   //使用链式调用,这里需要返回本类
    }

    @Override
    AbstractBuilder customMem(String mem) {
        phone.mem = mem;
        return this;
    }

    @Override
    AbstractBuilder customDisk(String disk) {
        phone.disk = disk;
        return this;
    }

    @Override
    AbstractBuilder customCam(String cam) {
        phone.cam = cam;
        return this;
    }
}

AbstractBuilder

package com.atguigu.design.creatation.builder;

/**
 * 抽象建造者
 */
public abstract class AbstractBuilder  {

    Phone phone;
    abstract AbstractBuilder customCpu(String cpu);
    abstract AbstractBuilder customMem(String mem);
    abstract AbstractBuilder customDisk(String disk);
    abstract AbstractBuilder customCam(String cam);

    Phone getProduct(){
        return phone;
    }
}

MainTest

package com.atguigu.design.creatation.builder;

public class MainTest {

    public static void main(String[] args) {

        AbstractBuilder builder = new XiaomiBuilder();

        //链式建造者
        Phone phone = builder.customCpu("骁龙8个8")
                .customCam("2亿")
                .customDisk("1T")
                .customMem("16G")
                .getProduct();
        System.out.println(phone);

        Phone build = Phone.builder()
                .cpu("1")
                .mem("2")
                .cam("3")
                .disk("4")
                .build();
        System.out.println(build);
    }
}

2.结构型模式

怎样组合对象/类

类结构模式

对象结构模式

1.适配器

两个不兼容接口之间适配的桥梁

Player接口

public interface Player {
    String play();
}

Translator接口

public interface Translator {
    String translate(String content);
}

Zh_JPTranslator

public class Zh_JPTranslator implements Translator{
    @Override
    public String translate(String content) {
        if("你好".equals(content)){
            return "空尼几哇";
        }
        if ("什么".equals(content)){
            return "纳尼";
        }
        return "*******";
    }
}

MoviePlayer

public class MoviePlayer implements Player {
    @Override
    public String play() {
        System.out.println("正在播放:宋老师的宝贵时间.avi");
        String content = "你好";
        System.out.println(content);  //并且打印出字幕
        return content;
    }
}

类结构模型适配器

import com.atguigu.design.structural.adapter.Player;
import com.atguigu.design.structural.adapter.Zh_JPTranslator;

/**
 * 继承的方式:类结构模型,适配转换到了翻译器的功能上
 * 类适配器  : 继承+实现
 */
public class JPMoviePlayerAdapter extends Zh_JPTranslator implements Player {

    private Player target;//被适配对象
    public JPMoviePlayerAdapter(Player target){
        this.target = target;
    }

    @Override
    public String play() {

        String play = target.play();
        //转换字幕
        String translate = translate(play);
        System.out.println("日文:"+translate);
        return play;
    }
}

-----------------------------------------------------------------------------------------------
//测试类
public class MainTest {

    public static void main(String[] args) {

        MoviePlayer player = new MoviePlayer();
        player.play();

    }
}

对象结构模型适配器

/**
 * 组合的方式:对象结构模型,适配转换到了翻译器的功能上
 * (继承、组合)、封装、多态
 */

public class JPMoviePlayerAdapter implements Player {

    //组合的方式
    private Translator translator = new Zh_JPTranslator();
    private Player target;//被适配对象(原有的接口)

    public JPMoviePlayerAdapter(Player target){
        this.target = target;
    }

    @Override
    public String play() {
        String play = target.play();
        //转换字幕
        String translate = translator.translate(play);
        System.out.println("日文:"+translate);
        return play;
    }
}

2.桥接模式

将抽象与实现分离(当多个变化因素在多个对象间共享时)

public class IPhone  extends AbstractPhone{
    @Override
    String getPhone() {
        return "IPhone:"+sale.getSaleInfo();
    }
}
public abstract class AbstractSale {

    private String type;
    private Integer price;

    public AbstractSale(String type,Integer price){
        this.type = type;
        this.price = price;
    }

    String getSaleInfo(){
        return "渠道:"+type+"==>"+"价格:"+price;
    }

    void howToSale(){
    }
}
/**
 * 1、抽象手机类
 *  手机有各种销售渠道价格都不一样
 *
 */
public abstract class AbstractPhone {

    //桥接在此.....设计期间就得想好
    //【真正会引起此类变化的一个维度直接抽取出来,通过组合的方式接起来】
    //桥接+适配器 ...
    AbstractSale sale; //分离渠道【桥接的关注点】

    /**
     * 当前手机的描述
     */
    abstract String getPhone();

    public void setSale(AbstractSale sale) {
        this.sale = sale;
    }
}
public class StudentSale extends AbstractSale{
    public StudentSale(String type, Integer price) {
        super(type, price);
    }
}
--------------------------------------------测试类----------------------------------------------
/**
 * 省去了创建很多类
 */
public class MainTest {

        IPhone iPhone = new IPhone();
        //set的是 对象的属性
        iPhone.setSale(new StudentSale("学生",1));
        //通过抽象的具体属性类 获取 抽象属性
        String phone = iPhone.getPhone();
        System.out.println(phone);
    }
}

3.装饰器模式

向一个现有的独享添加新的功能,同时不改变其结构

//适配器是连接两个类,增强一个类 //装饰器只装饰一个类

public class LeiTikTok implements ManTikTok{
    @Override
    public void tiktok() {
        System.out.println("雷丰阳,tiktok.... ");
    }
}
/**
 * 抽象构建
 */
public  interface ManTikTok {
   void tiktok();
}
/**
 * 抽象装饰器
 * 抖音直播装饰器
 */
public interface TiktokDecorator extends ManTikTok{
    void enable();
}
public class ZhangTikTok implements ManTikTok{
    @Override
    public void tiktok() {
        System.out.println("张三,tiktok.... ");
    }
}
/**
 * 美颜装饰器
 *      装饰谁
 *  装饰器只关系增强这个类的方法。
 */
public class MeiYanDecorator implements TiktokDecorator{

    private ManTikTok manTikTok;
    public MeiYanDecorator(ManTikTok manTikTok){
        this.manTikTok = manTikTok;
    }

    @Override
    public void tiktok() {

        //开启美颜
        enable(); //调用继承里边的方法

        //我开始直播
        manTikTok.tiktok();
    }

    /**
     * 定义的增强功能
     */
    @Override
    public void enable() { //对继承的方法进行增强
        System.out.println("看这个美女.....");
        System.out.println("花花花花花花花花花花花");
    }
}
/**
 * 核心:想要不改变原来接口方法的情况下扩展新功能,或者增强方法.....
 */
public class MainTest {

    public static void main(String[] args) {
        //被装饰对象
        ManTikTok manTikTok = new LeiTikTok();

        MeiYanDecorator decorator = new MeiYanDecorator(manTikTok);
        decorator.tiktok();//通过这个调用(重写实现类的方法),  然后  增强继承里边的方法
    }
}

4.代理模式

1.静态代理

//被代理对象是一个接口, 从代理对象类实现增强功能 和  输出原始功能

/**
 * 抽象主体。被代理角色能干什么
 */
public  interface ManTikTok {
   void tiktok();
}

LiMingTiktokProxy

/**
 * 代理一般都是和被代理对象属于同一个接口
 */
public class LiMingTiktokProxy implements ManTikTok{

    private ManTikTok manTikTok; //被代理对象
    public LiMingTiktokProxy(ManTikTok manTikTok){
        this.manTikTok = manTikTok;
    }

    /**
     * 宋喆(代理)  宝强(被代理对象)
     */
    @Override
    public void tiktok() {
        //这里是增强功能
        System.out.println("渲染直播间....");
        System.out.println("课程只要666,仅此一天....");
        //这里调用的是主方法
        manTikTok.tiktok();
    }
}

ZhangTikTok

public class ZhangTikTok implements ManTikTok {
    @Override
    public void tiktok() {
        System.out.println("张三,tiktok.... ");
    }
}

LeiTikTok

/**
 * 主体 主类   被代理的对象
 */
public class LeiTikTok implements ManTikTok {
    @Override
    public void tiktok() {
        System.out.println("雷丰阳,tiktok.... ");
    }
}

MainTest

/**
 * 代理的东西不一样,每一种不同的被代理类Person、Dog、Cat,创建不同的静态代理类
 */
public class MainTest {
    public static void main(String[] args) {
        LiMingTiktokProxy proxy = new LiMingTiktokProxy(new LeiTikTok());
        proxy.tiktok();
        //静态代理就是装饰器
        //装饰器模式是代理模式的一种
    }
}

2.动态代理

 * 动态代理模式:
 * JDK要求被代理对象必须有接口
 * 代理对象和目标对象的相同点在于都是同一个接口

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

/**
 * 敲10遍
 * @param <T>
 */
public class JdkTiktokProxy<T> implements InvocationHandler {

    private T target;
    //接受被代理对象
    JdkTiktokProxy(T target){
        this.target = target;
    }
    /**
     * 获取被代理对象的  代理对象
     * @param t
     * @param <T>
     * @return
     */
    public static<T> T getProxy(T t) {

        /**
         * ClassLoader loader, 当前被代理对象的类加载器
         * Class<?>[] interfaces, 当前被代理对象所实现的所有接口
         * InvocationHandler h,
         *  当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法
         */
        Object o = Proxy.newProxyInstance(
                t.getClass().getClassLoader(),
                t.getClass().getInterfaces(), //必须接口
                new JdkTiktokProxy(t));
        return (T)o;
    }

    /**
     * 定义目标方法的拦截逻辑;每个方法都会进来的
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy,
                         Method method,
                         Object[] args) throws Throwable {

        //反射执行
        System.out.println("真正执行被代理对象的方法");
        Object invoke = method.invoke(target, args);
        System.out.println("返回值:一堆美女");
        return invoke;
    }
}

3.cglib代理

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

import java.lang.reflect.Method;

/**
 * 1、使用cglib帮我们创建出代理对象
 */
public class CglibProxy {

    //为任意对象创建代理
    public static<T> T createProxy(T t){
        //1、创建一个增强器
        Enhancer enhancer = new Enhancer();

        //2、设置要增强哪个个类的功能。增强器为这个类动态创建一个子类
        enhancer.setSuperclass(t.getClass());

        //3、设置回调
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj,
                                    Method method,  //为了能获取到原方法的一些元数据信息
                                    Object[] args,
                                    MethodProxy proxy) throws Throwable {
                //编写拦截的逻辑   这里实现的是增强的逻辑
                System.out.println("cglib上场le .......xxx");
                //当前方法的信息
//                method.get
//                method.getAnnotation()
                //目标方法进行执行
                Object invoke = proxy.invokeSuper(obj,args);
                return invoke;
            }
        });

        Object o = enhancer.create();
        return (T) o;
    }

}

测试类

public class CglibTest {

    public static void main(String[] args) {

        //原来的对象都不用new
        LeiTikTok tikTok = new LeiTikTok();

        LeiTikTok proxy = CglibProxy.createProxy(tikTok);

        proxy.tiktokHaha();
    }
}

5.外观模式

//提供一个统一入口,相当于网关转发

6.组合模式

相当于多叉树,字典树

7.享元模式

尝试重用现有的同类对象,如果未匹配到的对象,则创新建对象

AbstractWaitressFlyweight

package com.atguigu.design.structural.flyweight;

/**
 * 可共享和不可共享状态
 */
public abstract class AbstractWaitressFlyweight {

    boolean canService = true;//能否服务

    //正在服务。   享元的不可共享属性留给外部进行改变的接口
    abstract void service();
    //服务完成。   享元的不可共享属性留给外部进行改变的接口
    abstract void end();

    public boolean isCanService() {
        return canService;
    }
}

BeautifulWaitress

package com.atguigu.design.structural.flyweight;

import lombok.AllArgsConstructor;

/**
 * 具体享元类
 */
@AllArgsConstructor
public class BeautifulWaitress extends AbstractWaitressFlyweight{
    String id;//工号
    String name;//名字
    int age;//年龄
    //以上是不变的

    @Override
    void service() {
        System.out.println("工号:"+id+";"+name+" "+age+" 正在为您服务...");
        //可以服务,为false,外部不可以使用
        this.canService = false;
    }

    @Override
    void end() {
        //不可以服务,外部不能共享此变量
        System.out.println("工号:"+id+";"+name+" "+age+" 服务结束...请给五星好评");
        //调用end方法的时候设置为 true,会把池中的对象释放,下面才能继续使用
        this.canService = true;
    }
}
package com.atguigu.design.structural.flyweight;

import java.util.*;

/**
 * 足道店:这相当于享元工厂
 *      店里面很多服务员。
 *
 * 享元和原型
 * 1、享元返回的是这个本人。
 * 2、原型返回的是克隆人。
 *
 */
public class ZuDao {

    private static Map<String,AbstractWaitressFlyweight> pool = new HashMap<>();
    //享元,池子中有对象
    static {
        BeautifulWaitress waitress =
                new BeautifulWaitress("1111","张三",18);

        BeautifulWaitress waitress2 =
                new BeautifulWaitress("9527","李四",20);

        pool.put(waitress.id,waitress);
        pool.put(waitress2.id,waitress2);
    }

    public void addWaitress(AbstractWaitressFlyweight waitressFlyweight){
        pool.put(UUID.randomUUID().toString(),waitressFlyweight);
    }

    public static AbstractWaitressFlyweight getWaitress(String name){
        AbstractWaitressFlyweight flyweight = pool.get(name);
        if(flyweight == null){
            for (AbstractWaitressFlyweight value : pool.values()) {
                //当前共享对象能否是否
                if(value.isCanService()){
                    return value;
                }
            };
            return null;
        }
        return flyweight;
    }
}

MainTest

package com.atguigu.design.structural.flyweight;

/**
 *
 */
public class MainTest {

    public static void main(String[] args) {

        //1、我
        AbstractWaitressFlyweight waitress = ZuDao.getWaitress("");
        waitress.service();
        System.out.println(waitress);
        //2、佟老师
        AbstractWaitressFlyweight waitress1 = ZuDao.getWaitress("");
        waitress1.service();
        System.out.println(waitress1);

        waitress1.end(); //这里释放 修改状态,后面才能继续使用
        //3、刘佳林
        AbstractWaitressFlyweight waitress2 = ZuDao.getWaitress("");
        System.out.println(waitress2);

    }
}

3.行为模式

1.模板模式

调用父类的方法

抽象父类

package com.atguigu.design.behavioral.template;

/**
 * 1、定义模板
 */
public abstract class CookTemplate {

    /**
     * 定义算法:  定义好了模板
     * 父类可以实现某些步骤
     * 留关键给子类
     */  
    public void cook(){ //核心方法  规定好方法,不能变
        //定义算法步骤
        heating();   //v
        addfood();
        addsalt();
        stirfry();   //v
        end();      //v
    }

    //加热方法
    public void heating(){
        System.out.println("开火...");
    };

    //添加食物
    public abstract void addfood();

    //加盐 需要调用者自己去实现
    public abstract void addsalt();

    //翻炒 已经实现
    public  void stirfry(){
        System.out.println("翻炒中...");
    };

    //出锅
    public  void end(){
        System.out.println("出锅....");
    };

}

实现类

public class AutoCookMachine extends CookTemplate{

    @Override
    public void addfood() {
        System.out.println("放了三个小白菜");
    }

    @Override
    public void addsalt() {
        System.out.println("放了三勺盐");
    }
}
-----------------------------------------------------------------------------------------------测试类   
public class MainTest {

    public static void main(String[] args) {

        AutoCookMachine cookMachine = new AutoCookMachine();

        //调用抽象的具体方法调用,    抽象类继承类去实现抽象类 未实现的功能
        cookMachine.cook();

    }
}

2.策略模式

// 一个策略接口,通过调用接口实现去完成对应的目标

/**
 * 游戏策略
 */
public interface GameStrategy {

    //战斗策略
    void warStrategy();

}

策略的应用/调用

/**
 * 环境类
 */
public class TeamGNR {

    //抽取游戏策略算法,并进行引用
    private GameStrategy gameStrategy;

    public void setGameStrategy(GameStrategy gameStrategy) {
        this.gameStrategy = gameStrategy;
    }

    public void startGame(){
        System.out.println("游戏开始.....");
        //游戏策略
        gameStrategy.warStrategy();//调用的是 接口的具体实现类的方法
        System.out.println("win......");
    }
}

实现类

/**
 * 冲锋向前策略
 */
public class UziStrategy implements GameStrategy{
    @Override
    public void warStrategy() {
        System.out.println("uzi.....");
    }
}

--------------------------------------------------------------------------------------------
测试类
public class MainTest {

    public static void main(String[] args) {

        TeamGNR gnr = new TeamGNR();

        gnr.setGameStrategy(new RandomStrategy());
        gnr.startGame();
    }
}

3.状态模式

在接口中调用下一个方法(和策略模式的区别), 可以连续调用

利用next方法,实现 接口实现类的多个方法来回调用

/**
 * 抽象状态
 */
public interface TeamState {

    //玩游戏
    void playGame();

    //切换到下一个状态
    TeamState next();
}

核心类

/**
 * 环境类:
 */
public class SKTTeam {

    private TeamState teamState;

    public void setTeamState(TeamState teamState) { //传入接口类,实际执行的是实现类
        this.teamState = teamState;
    }

    //开始游戏
    public void startGame(){
        //状态不同会导致不同的游戏结果
        teamState.playGame();
    }

    //下一个状态
    void nextState(){
        teamState = teamState.next();
    }
}

状态流转类

/**
 * 竞赛状态
 */
public class MatchState implements TeamState{
    @Override
    public void playGame() {
        System.out.println("全力以赴打比赛....");
    }

    //状态模式的核心
    @Override
    public TeamState next() {
        return new VocationState();
    }
}
package com.atguigu.design.behavioral.state;

/**
 * 休假状态
 */
public class VocationState implements TeamState {
    @Override
    public void playGame() {
        System.out.println("三亚旅游真舒服....饿了...不玩游戏");
        //状态流转

    }

    @Override
    public TeamState next() {
        return new BeafNodleState();
    }
}
package com.atguigu.design.behavioral.state;

/**
 * 吃牛肉面状态
 */
public class BeafNodleState implements TeamState {

    @Override
    public void playGame() {
        System.out.println("饱饱的一顿牛肉面......中了诅咒,输了");
    }

    @Override
    public TeamState next() {
        return new MatchState();
    }
}

测试类

package com.atguigu.design.behavioral.state;

/**
 * 状态切换
 */
public class MainTest {

    public static void main(String[] args) {

        SKTTeam sktTeam = new SKTTeam();
        TeamState state = new VocationState();//首先执行的是这个状态
        sktTeam.setTeamState(state);
        sktTeam.startGame();
        sktTeam.nextState();// 调用下一个状态

        sktTeam.startGame();
        sktTeam.nextState();

        sktTeam.startGame();
    }
}

4.中介者模式

网状关系变为星状关系, 需要一个公用类 ,各个实现类给公用类赋值

/**
 * 抽象机长
 */
public abstract class Captain {

    //起飞
    abstract void fly();
    //降落
    abstract void land();
    //完成
    abstract void success();

}

中介类

/**
 * 塔台:中介者
 *
 * 网状变为星状
 */
public class ControlTower {

    private boolean canDo = true;

    //接受请求...              //抽象类, 需要的是具体的实现的值  传的是当前的类
    public void acceptRequest(Captain captain,String action){
        if("fly".equals(action)||"land".equals(action)){
            //
            if(canDo == true){
                System.out.println("允许......");
                canDo = false;
            }else {
                System.out.println("不允许.....");
            }
        }
        if("success".equals(action)){
            canDo = true;
        }
    }
}

具体的实现

/**
 * 四川8633机长
 */
public class SC8633 extends Captain{
    ControlTower controlTower ;

    public void setControlTower(ControlTower controlTower) {
        this.controlTower = controlTower;
    }

    @Override
    void fly() {
        System.out.println("SC8633 请求起飞......");
        //问每个机长能否起飞?
        controlTower.acceptRequest(this,"fly");

    }

    @Override
    void land() {

        System.out.println("SC8633 请求降落......");
        //问每个机长能否起飞?
        controlTower.acceptRequest(this,";land");
    }

    @Override
    void success() {

        System.out.println("SC8633 完成......");
        //问每个机长能否起飞?
        controlTower.acceptRequest(this,"fly");
    }
}
package com.atguigu.design.behavioral.mediator;

import java.util.List;

/**
 * 海南8778
 */
public class HU8778 extends Captain{

    ControlTower controlTower;

    public void setControlTower(ControlTower controlTower) {
        this.controlTower = controlTower;
    }

    @Override
    void fly() {
        System.out.println("HU8778请求起飞......");
        //问每个机长能否起飞?
        controlTower.acceptRequest(this,"fly");
    }

    @Override
    void land() {
        System.out.println("HU8778请求降落......");
        controlTower.acceptRequest(this,"land");
    }

    @Override
    void success() {
        System.out.println("完成......");
        controlTower.acceptRequest(this,"success");
    }
}

5.观察者模式

package com.atguigu.design.behavioral.observer;

import java.util.ArrayList;
import java.util.List;

/**
 * 主播
 * 双向观察
 */
public class MMTikToker  extends AbstractTikToker{

    //1、观察者的核心1
    List<AbstractFans> fansList = new ArrayList<>();

    void startSell() {
        System.out.println("雷丰阳... 开始卖货...源码设计课");
        notifyFans("我开始卖东西了,是源码设计课,只要666");//调用,通知观察者的方法
    }
    void endSell() {
        System.out.println("雷丰阳... 结束卖货...源码设计课");
        notifyFans("课已经卖完了,记得五星好评...");
    }

    //添加粉丝
    @Override
    void addFans(AbstractFans fans) {
        fansList.add(fans);
    }

    //通知所有观察者
    @Override
    void notifyFans(String msg) {
        //1、所有粉丝拿来通知
        for (AbstractFans fans : fansList) {
            fans.acceptMsg(msg);//调用通知粉丝的抽象方法去找对应的实现
        }
    }
}
package com.atguigu.design.behavioral.observer;

/**
 * 抖音主播
 *
 * 粉丝观察主播....
 */
public abstract class AbstractTikToker {

    //添加粉丝
    abstract void addFans(AbstractFans fans);

    //通知粉丝
    abstract void notifyFans(String msg);
}
package com.atguigu.design.behavioral.observer;

import java.util.List;

/**
 * 抽象观察者
 */
public abstract class AbstractFans {

    List<AbstractTikToker> tikTokers;//双向观察

    //通知粉丝
    abstract void acceptMsg(String msg);

    void follow(AbstractTikToker tikToker){
        //主播增粉了
    tikToker.addFans(this);
//        for (AbstractTikToker toker : tikTokers) {
//
//        }
    };

}
public class HumanFans extends AbstractFans {
    @Override
    void acceptMsg(String msg) {
        System.out.println("主播说:"+msg);
    }
}

public class RobotFans extends AbstractFans {
    @Override
    void acceptMsg(String msg) {
        System.out.println("呸....");
    }
}

测试方法

public class MainTest {

    public static void main(String[] args) {

        MMTikToker lei = new MMTikToker();

        lei.startSell();

        RobotFans fans1 = new RobotFans();
        RobotFans fans2 = new RobotFans();
        RobotFans fans3 = new RobotFans();
        fans1.follow(lei);
        fans2.follow(lei);
        fans3.follow(lei);

        HumanFans humanFans = new HumanFans();
        humanFans.follow(lei);

        System.out.println("=====>");

        lei.endSell();
    }
}

6.备忘录模式

//抽取公用对象属性,然后对象属性值对拷

import lombok.Data;

/**
 * 游戏记录。需要保存的内部状态信息,
 *      也叫备忘录信息
 */
@Data
public class GameRecord {
    Integer id; //代表生成记录的id
    Integer coin;//剩余金币
    Integer hp;//血量
    Integer mp;//蓝量
    Integer level;//等级
}
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * 游戏服务器
 * 管理者
 */
public class GameServer {

    //管理备忘录信息的
    Map<Integer,GameRecord> records = new HashMap<>();
    int i = 1;

    void add(GameRecord gameRecord){
        gameRecord.setId(i++);
        records.put(gameRecord.id,gameRecord);
    }

    LeiGamer getRecord(Integer id) throws Exception {
        GameRecord gameRecord = records.get(id);
        //获取到备忘录里面的内容以后还要逆转

        LeiGamer leiGamer = new LeiGamer();
//        leiGamer.setCoin(gameRecord.getCoin());

        //BeanUtils:工具类,属性对拷
        BeanUtils.copyProperties(leiGamer,gameRecord);

        return  leiGamer;
    }

}
package com.atguigu.design.behavioral.memento;

import lombok.Data;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * 游戏者: 游戏发起人
 * 当前游戏信息
 */
@Data
public class LeiGamer  {
    Integer coin;//剩余金币
    Integer hp;//血量
    Integer mp;//蓝量
    Integer level;//等级
    //以上的是内部状态,我们需要记录保存的信息

    GameServer gameServer = new GameServer();

    //保存游戏记录
    void saveGameRecord() throws Exception {
        System.out.println("正在保存当前记录....");
        GameRecord gameRecord = new GameRecord();
        //当前游戏信息保存到备忘录
        BeanUtils.copyProperties(gameRecord,this);
        //
        gameServer.add(gameRecord);
    }

    //从备忘录获取游戏历史存档
    LeiGamer getFromMemento(Integer id) throws Exception {
        System.out.println("获取历史存档信息....");
        LeiGamer record = gameServer.getRecord(id);
        return record;
    }

    //玩游戏
    void playGame(){
        int i = new Random().nextInt();
        System.out.println("......(〃'▽'〃)......"+i);

        coin = i;
        hp = i;
        mp = i;
        level = i;

    }

    //退出游戏
    void exitGame() throws Exception {
        System.out.println("退出&存档");
        saveGameRecord();
    }

}
//测试类
package com.atguigu.design.behavioral.memento;

/**
 * 1、备忘录的设计(提取属性)
 * 2、备忘录对象和原对象的互转操作(BeanUtils属性对拷)
 *      序列化
 *      保存数据库
 */
public class MainTest {

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

        LeiGamer leiGamer = new LeiGamer();

        leiGamer.playGame();

        //第一次保存
        leiGamer.saveGameRecord();

        leiGamer.playGame();

        leiGamer.playGame();

        leiGamer.saveGameRecord();

        LeiGamer fromMemento = leiGamer.getFromMemento(1);

        fromMemento.playGame();

    }
}

7.解释器模式(很少用/解释器常用)

入口类

//给分析对象一个语言
package com.atguigu.design.behavioral.interpreter;

import java.util.HashSet;
import java.util.Set;

/**
 * 环境类:
 * 风景区
 */
public class Area {
    Set<String> city = new HashSet<>();

    Set<String> type = new HashSet<>();
    IDCardExpression idCardReader;//读卡器,表达式解析器

    //环境类持有表达式

    public Area(){
//        {"武汉市","上海市"};//免费城市
//        {"医生","老人","儿童"};//免费人群
        city.add("武汉市");
        city.add("上海市");

        type.add("医生");
//        type.add("老人");
        type.add("儿童");

        //终结表达式
        TerminalExpression city =
                new TerminalExpression(this.city, ":");
        TerminalExpression type =
                new TerminalExpression(this.type, "-");

        //以上满足一个即可
        idCardReader = new OrExpression(city,type);

    }

    /**
     * 传入表达式,判断当前表达式是否指定为免费人群
     * @param expression
     */
    void getTicket(String expression){
        boolean interpret = idCardReader.interpret(expression);
        if(interpret){
            System.out.println("恭喜你,免票通过....");
        }else {
            System.out.println("对不起,请2元购票....");
        }
    }
}

解析逻辑抽象类

/**
 * 身份信息表达式
 * 表达式的解析
 *
 */
public abstract class IDCardExpression {

    /**
     * 定义解析逻辑
     * 假设我们需要解析的信息格式为:
     *      上海市:张文宏-医生
     *      武汉市:雷丰阳-程序员
     *      北京市:宋宋-老人
     *  表达式中,“:”以前的是城市,“-”以后的是职业
     * @param expression
     * @return
     */
    abstract boolean interpret(String expression);
}

解析逻辑具体实现--终结符表达式

package com.atguigu.design.behavioral.interpreter;

import java.util.Set;

/**
 * 终结符表达式
 *
 * 多少种解析规则就需要定义多少种规则类
 *
 */
public class TerminalExpression extends IDCardExpression {

    IDCardExpression childExp;

    Set<String> data;  //免费数据
    String symbol; //定义解析用的符号如  : -

    public TerminalExpression( Set<String>  data,String symbol){
        this.data = data;
        this.symbol = symbol;
    }

    @Override
    boolean interpret(String expression) {
        //上海市:张文宏-医生
        //1、先按照指定符号分割
        String[] split = expression.split(symbol);

        // 冒号:  上海市              张文宏-医生
        // 短横线  上海市:张文宏       医生
        boolean result = false;
        for (String s : split) {
            if(data.contains(s)){
                return true;
            };//说明是免费的信息里面的
        }

        //可以继续子解析
//        childExp.interpret(expression);

        //不在免费行列
        return false;
    }
}

解析逻辑具体实现--非终结符表达式

/**
 * 非终结表达式  (包含两个终结表达式,只要满足一个终结表达式即可以通过)
 */
public class OrExpression extends IDCardExpression {

    //组合两个终结表达式。最终的判断结果是终结表达式判断出来的,这个表达式只是一个桥梁
    private IDCardExpression cityExp;
    private IDCardExpression typeExp;

    public OrExpression(IDCardExpression cityExp, IDCardExpression typeExp) {
        this.cityExp = cityExp;
        this.typeExp = typeExp;
    }

    @Override
    boolean interpret(String expression) {

        //定义所有终结表达式的合并逻辑
        return cityExp.interpret(expression) || typeExp.interpret(expression);
    }
}

测试类

package com.atguigu.design.behavioral.interpreter;

public class MainTest {

    public static void main(String[] args) {

        Area area = new Area();
        /**
         *  上海市:张文宏-医生
         *  武汉市:雷丰阳-程序员
         *  北京市:宋宋-老人
         */
        String sr = "武汉市:雷丰阳-程序员";

        area.getTicket(sr);

    }
}

8.命令模式

先调用command 实现类的命令, 在调用实现类中调用的方法

/**
 * 抽象命令类
 * Controller、Service、Dao接口
 *
 * Service
 */
public interface  Command {

    /**
     * 命令的执行方法
     */
    void execute();
}
package com.atguigu.design.behavioral.command;

/**
 * 线上课命令
 *
 * Controller {
 *     xxService
 *     aaService
 *
 *
 *     //宏命令
 *     order(){
 *         //结账
 *         //扣库存
 *         //出账单
 *         ....
 *     }
 *
 * }
 */
public class OnlineCommand implements Command{

    //Dao
    private LeiReceiver receiver = new LeiReceiver();
    @Override
    public void execute() {
        System.out.println("要去上(吹)课(牛)....");
        receiver.online();
    }
}
package com.atguigu.design.behavioral.command;

/**
 * 命令接受者(执行者)。
 */
public class LeiReceiver {

    public void online(){
        System.out.println("leifengyang 在线上直播大厂课......");
    }
    public void travel(){
        System.out.println("leifengyang 出差.....");
    }
}
/**
 * 命令接受者(执行者)。
 */
public class LeiReceiver {

    public void online(){
        System.out.println("leifengyang 在线上直播大厂课......");
    }
    public void travel(){
        System.out.println("leifengyang 出差.....");
    }
}

---------------------------------------------------测试类--------------------------------------

public class MainTest {

    public static void main(String[] args) {

        TeacherTongInvoker invoker = new TeacherTongInvoker();
        //先调用command 实现类的命令,  在调用实现类中调用的方法
        invoker.setCommand(new OnlineCommand());

        invoker.call();
    }
}

9.迭代器模式

package com.atguigu.design.behavioral.iterator;

import java.util.ArrayList;
import java.util.List;

/**
 * 抽象聚合类
 */
public abstract class BeautifulMan {

    //不方便暴露给外界的集合。只允许外界获取而不可以操作
    private List<String> girlFriends = new ArrayList<>();

    void likeYou(String name){
        girlFriends.add(name);
    };
    void sayBye(String name){
        girlFriends.remove(name);
    };

    /**
     * 获取迭代器
     * @return
     */
    public Itr getIterator(){
        return new Iterator();
    }

    /**
     * 具体迭代器
     */
    class Iterator implements Itr{

       private int cursor = 0; //当前指针

       @Override
       public boolean hasNext(){
           return cursor < girlFriends.size();
       }

        @Override
       public String next(){
           //第一次调用返回第一个数据
           //下一次再调用自动访问下一个数据
           String s = girlFriends.get(cursor);
           cursor++;
           return s;
       }

        @Override
        public String firstLove() {
            return girlFriends.get(0);
        }

        @Override
        public String current() {
            return girlFriends.get(girlFriends.size()-1);
        }
    }

    /**
     * 抽象迭代器,写在外部该怎么写?
     */
    interface Itr {
        //有没有下一个
        boolean hasNext();
        //返回下一个
        String next();

        //返回初恋(第一个)
        String firstLove();

        //返回现任(最后一个女朋友)
        String current();
    }

}
public class MaYuCheng extends BeautifulMan{

}
public class MainTest {

    public static void main(String[] args) {

        MaYuCheng cheng = new MaYuCheng();

        cheng.likeYou("王刚");
        cheng.likeYou("李强");
        cheng.likeYou("赵根");

        BeautifulMan.Itr itr = cheng.getIterator();
        String s = itr.firstLove();
        System.out.println(s);

        String current = itr.current();
        System.out.println(current);

        System.out.println("=================");
        while (itr.hasNext()){
            String next = itr.next();
            System.out.println(next);
        }
    }
}

10.访问者模式

11.责任链模式

1.简单责任链模式

public class Teacher {

    private String name;

    //下一个处理的老师;1、链条的引用点
    private Teacher next;

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

    public void setNext(Teacher next) {
        this.next = next;
    }

    public Teacher getNext() {
        return next;
    }

    //链条调用方法
    void handleRequest() {
        System.out.println(this + "正在处理.....");
        //2、如果链式调用,最后没有了,不能往下调用,要做判断
        if (next != null) {
            next.handleRequest();
        }
    }

    ;

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                '}';
    }
}

测试类

/**
 *         //1、链条的引用点
 *         //2、下一个继续
 *         //3、构造链条
 *
 *   回旋责任链
 *   Filter:1 -- 2 -- 3 -- 本人 -- 3 -- 2 -- 1
 *
 */
public class MainTest {

    public static void main(String[] args) {

        Teacher leifengyang = new Teacher("Leifengyang");

        Teacher xiaokui = new Teacher("xiaokui");

        Teacher mengmeng = new Teacher("mengmeng");

        leifengyang.setNext(xiaokui);
        xiaokui.setNext(mengmeng);

        leifengyang.handleRequest();

    }
}
版权声明:原创作品,允许转载,转载时务必以超链接的形式表明出处和作者信息。否则将追究法律责任。来自海汼部落-123456789987654321,http://hainiubl.com/topics/75897
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,可用Emoji的自动补全, 在输入的时候只需要 ":" 就可以自动提示了 :metal: :point_right: 表情列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif,教程
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter