设计模式学习笔记

1.单例模式

package instance;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

public class Singleton {

    //1.
    public static Map<String, String> cache = new ConcurrentHashMap<>();


    //2.
    private static Singleton instance;

    private Singleton() {
    }

    //3.
    public static Singleton getInstance1() {
        if (instance != null) {
            return instance;
        }
        instance = new Singleton();
        return instance;
    }


    //4.
    public static synchronized Singleton getInstance2() {
        if (instance != null) {
            return instance;
        }
        instance = new Singleton();
        return instance;
    }

    //5.
    public static Singleton getInstance3() {
        if (instance != null) {
            return instance;
        }
        synchronized (Singleton.class) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
        return instance;
    }

    //6.
    public static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();

    public static final Singleton getInstance4() {
        for (; ; ) {
            Singleton instance = INSTANCE.get();
            if (instance != null) {
                return instance;
            }
            INSTANCE.compareAndSet(null, new Singleton());
            return INSTANCE.get();
        }
    }

    public enum Singleton5 {
        INSTANCE;

        public void test() {
            System.out.println("enum-> test!");
        }

    }

    public static void main(String[] args) {
        Singleton5.INSTANCE.test();
    }


}

2.原型模式

解决创建重复对象,且该部分对象内容比较复杂,生成过程可能从库或RPC接口中获取数据耗时较长,因此采用克隆方式节省时间;
通过克隆方式创建复杂对象,可以避免做初始化操作,不需要与类中所属的其他类耦合等;

package prototype.retry.util;

import java.util.Map;

public class Topic {
    private Map<String,String> options;
    private String key;

    public Topic(Map<String, String> options, String key) {
        this.options = options;
        this.key = key;
    }

    public Map<String, String> getOptions() {
        return options;
    }

    public void setOptions(Map<String, String> options) {
        this.options = options;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

package prototype.retry.util;

import java.util.*;

public class TopicRandomUtil {

    static public Topic random(Map<String, String> option, String key) {
        Set<String> keySet = option.keySet();
        ArrayList<String> keyList = new ArrayList<>(keySet);
        Collections.shuffle(keyList);
        HashMap<String, String> optionNew = new HashMap<>();
        int idx = 0;
        String keyNew = "";
        for (String next : keySet) {
            String randomKey = keyList.get(idx++);
            if (key.equals(next)) {
                keyNew = randomKey;
            }
            optionNew.put(randomKey, option.get(next));
        }
        return new Topic(optionNew, keyNew);

    }
}

package prototype.retry;

import prototype.design.AnswerQuestion;
import prototype.design.ChoiceQuestion;
import prototype.retry.util.Topic;
import prototype.retry.util.TopicRandomUtil;

import java.util.*;

public class QuestionBank {
    private String candidate;
    private String number;

    private ArrayList<ChoiceQuestion> choiceQuestionList = new ArrayList<>();
    private ArrayList<AnswerQuestion> answerQuestionList = new ArrayList<>();

    public QuestionBank append(ChoiceQuestion choiceQuestion) {
        choiceQuestionList.add(choiceQuestion);
        return this;
    }

    public QuestionBank append(AnswerQuestion answerQuestion) {
        answerQuestionList.add(answerQuestion);
        return this;
    }


    @Override
    protected Object clone() throws CloneNotSupportedException {
        QuestionBank questionBank = new QuestionBank();
        questionBank.choiceQuestionList = (ArrayList<ChoiceQuestion>) choiceQuestionList.clone();
        questionBank.answerQuestionList = (ArrayList<AnswerQuestion>) answerQuestionList.clone();

        //题目乱序
        Collections.shuffle(questionBank.choiceQuestionList);
        Collections.shuffle(questionBank.answerQuestionList);

        //选项乱序
        for (ChoiceQuestion choiceQuestion : questionBank.choiceQuestionList) {
            Topic random = TopicRandomUtil.random(choiceQuestion.getOption(), choiceQuestion.getKey());
            choiceQuestion.setOption(random.getOptions());
            choiceQuestion.setKey(random.getKey());
        }
        return questionBank;
    }

    public String getCandidate() {
        return candidate;
    }

    public void setCandidate(String candidate) {
        this.candidate = candidate;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public ArrayList<ChoiceQuestion> getChoiceQuestionList() {
        return choiceQuestionList;
    }

    public void setChoiceQuestionList(ArrayList<ChoiceQuestion> choiceQuestionList) {
        this.choiceQuestionList = choiceQuestionList;
    }

    public ArrayList<AnswerQuestion> getAnswerQuestionList() {
        return answerQuestionList;
    }

    public void setAnswerQuestionList(ArrayList<AnswerQuestion> answerQuestionList) {
        this.answerQuestionList = answerQuestionList;
    }

    @Override
    public String toString() {
        StringBuilder ret = new StringBuilder();
        ret.append("考生:").append(candidate);
        ret.append("考号:").append(number).append("\r\n");
        ret.append("一.选择题");
        for (int i = 0; i < choiceQuestionList.size(); i++) {
            ChoiceQuestion question = choiceQuestionList.get(i);
            ret.append(i + "." + question.getName()).append("\r\n");
            Set<Map.Entry<String, String>> entrySet = question.getOption().entrySet();
            entrySet.forEach((m) -> {
                ret.append(m.getKey() + "." + m.getValue()).append("\r\n");
            });
            ret.append("正确答案:" + question.getKey()).append("\r\n\r\n");
        }
        ret.append("二.问答题").append("\r\n");
        for (int i = 0; i < answerQuestionList.size(); i++) {
            ret.append(i + "." + answerQuestionList.get(i).getName()).append("\r\n");
            ret.append("正确答案:" + answerQuestionList.get(i).getKey()).append("\r\n");
            ret.append("\r\n");
        }
        return ret.toString();
    }
}

package prototype.retry;

import prototype.design.AnswerQuestion;
import prototype.design.ChoiceQuestion;

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

public class QuestionBankController {
    private QuestionBank questionBank = new QuestionBank();

    public QuestionBankController() {
        Map<String, String> map01 = new HashMap<>();
        map01.put("A", "JAVA2 EE");
        map01.put("B", "JAVA2 Card");
        map01.put("C", "JAVA2 ME");
        map01.put("D", "JAVA2 HE");
        map01.put("E", "JAVA2 SE");

        Map<String, String> map02 = new HashMap<>();
        map02.put("A", "JAVA程序的main方法必须写在类里面");
        map02.put("B", "JAVA程序可以有多个main方法");
        map02.put("C", "JAVA程序中类名必须和文件名一样");
        map02.put("D", "JAVA程序中main语句如果仅有一条,可以不适用{}括起来");

        Map<String, String> map03 = new HashMap<String, String>();
        map03.put("A", "变量由字⺟、下划线、数字、$符号随意组成;");
        map03.put("B", "变量不能以数字作为开头;");
        map03.put("C", "A和a在java中是同⼀个变量;");
        map03.put("D", "不同类型的变量,可以起相同的名字;");

        Map<String, String> map04 = new HashMap<String, String>();
        map04.put("A", "STRING");
        map04.put("B", "x3x;");
        map04.put("C", "void");
        map04.put("D", "de$f");

        Map<String, String> map05 = new HashMap<String, String>();
        map05.put("A", "31");
        map05.put("B", "0");
        map05.put("C", "1");
        map05.put("D", "2");

        questionBank.append(new ChoiceQuestion("JAVA所定义的版本中不包括", map01, "D"))
                .append(new ChoiceQuestion("下列说法正确的是", map02, "A"))
                .append(new ChoiceQuestion("变量命名规范说法正确的是", map03, "B"))
                .append(new ChoiceQuestion("以下()不是合法的标识符", map04, "C"))
                .append(new ChoiceQuestion("表达式(11+3*8)/4%3的值是", map05, "D"));

        questionBank.append(new AnswerQuestion("⼩红⻢和⼩⿊⻢⽣的⼩⻢⼏条腿", "4条腿"))
                .append(new AnswerQuestion("铁棒打头疼还是⽊棒打头疼", "头最疼"))
                .append(new AnswerQuestion("什么床不能睡觉", "⽛床"))
                .append(new AnswerQuestion("为什么好⻢不吃回头草", "后⾯的草没了"));

    }

    public String createPaper(String candidate, String number) throws CloneNotSupportedException {
        QuestionBank questionBankClone = (QuestionBank) questionBank.clone();
        questionBankClone.setCandidate(candidate);
        questionBankClone.setNumber(number);
        return questionBankClone.toString();
    }


    public static void main(String[] args) throws CloneNotSupportedException {
        QuestionBankController questionBankController = new QuestionBankController();
        String paper = questionBankController.createPaper("liyuan", "20181003114");
        System.out.println(paper);

    }
}


3.建造者模式

通过将多个简单对象通过一步步的组装构建出一个复杂对象的过程;
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示;
常运用于一些基本物料不会变,但其组合经常会变化的时候;
满足了单一职责原则以及可复用的技术,建造者独立,易扩展,便于控制细节风险。

package builder.retry;

import builder.design.ceiling.LevelTwoCeiling;
import builder.design.coat.DuluxCoat;
import builder.design.coat.LiBangCoat;
import builder.design.floor.ShengXiangFloor;
import builder.design.tile.MarcoPoloTile;

import java.math.BigDecimal;

public class Builder {
    public IMenu levelOne(Double area) {
        return new DecorationPackageMenu(new BigDecimal(area), "豪华欧式")
                .appendCeiling(new LevelTwoCeiling())//吊顶,二级顶
                .appendCoat(new DuluxCoat())//涂料,多乐士
                .appendFloor(new ShengXiangFloor());//地板,圣像
    }

    public IMenu levelTwo(Double area) {
        return new DecorationPackageMenu(new BigDecimal(area), "轻奢田园")
                .appendCeiling(new LevelTwoCeiling())
                .appendFloor(new LiBangCoat())
                .appendTile(new MarcoPoloTile());
    }
}

package builder.retry;

import builder.design.Matter;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class DecorationPackageMenu implements IMenu {

    private List<Matter> list = new ArrayList<>();//装修清单
    private BigDecimal price = BigDecimal.ZERO;//价格
    private BigDecimal area;//面积
    private String grade;//装修等级

    private DecorationPackageMenu() {
    }

    public DecorationPackageMenu(BigDecimal area, String grade) {
        this.area = area;
        this.grade = grade;
    }

    @Override
    public IMenu appendCeiling(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(new BigDecimal("0.2")).multiply(matter.price()));
        return this;
    }

    @Override
    public IMenu appendCoat(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(new BigDecimal("1.4")).multiply(matter.price()));
        return this;
    }

    @Override
    public IMenu appendFloor(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(matter.price()));
        return this;
    }

    @Override
    public IMenu appendTile(Matter matter) {
        list.add(matter);
        price = price.add(area.multiply(matter.price()));
        return this;
    }

    @Override
    public String getDetail() {
        StringBuilder ret = new StringBuilder("");
        ret.append("套餐等级:" + grade + "\r\n");
        ret.append("套餐价格:" + price.setScale(2, BigDecimal.ROUND_HALF_UP) + "元\r\n");
        ret.append("房屋面积:" + area.doubleValue() + " 平米\r\n");
        for (Matter matter : list) {
            ret.append(matter.scene()).append(": ")
                    .append(matter.brand()).append(", ")
                    .append(matter.model()).append(", 平米价格:")
                    .append(matter.price()).append(" 元。\r\n");
        }
        return ret.toString();
    }
}

package builder.retry;

import builder.design.Matter;

public interface IMenu {
    IMenu appendCeiling(Matter matter);//吊顶

    IMenu appendCoat(Matter matter);//涂料

    IMenu appendFloor(Matter matter);//地板

    IMenu appendTile(Matter matter);//地砖

    String getDetail();//详细
}


package builder.retry;

public class Main {
    public static void main(String[] args) {
        Builder builder = new Builder();
        System.out.println(builder.levelOne(132.52D).getDetail());
    }
}



4.抽象工厂模式

抽象工厂的创建和获取方式,可采用代理类的方式进行实现。所代理的类就是目前的Redis操作方法类,让这个类在不需要任何修改下,就可以实现调用集群A和集群B的数据服务;
常用于解决一个产品族有多个不同类型的产品;

package abstractFactory.retry_.design.factory;

import abstractFactory.retry_.design.impl.Color;
import abstractFactory.retry_.design.impl.Shape;

public abstract class AbstractFactory {

    public abstract Color getColor(String color);

    public abstract Shape getShape(String shape);
}

package abstractFactory.retry_.design.factory;

import abstractFactory.retry_.design.impl.Color;
import abstractFactory.retry_.design.impl.Shape;
import abstractFactory.retry_.design.impl.color.Blue;
import abstractFactory.retry_.design.impl.color.Green;
import abstractFactory.retry_.design.impl.color.Red;

public class ColorFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        switch (color) {
            case "RED": {
                return new Red();
            }
            case "BLUE": {
                return new Blue();
            }
            case "GREEN": {
                return new Green();
            }
            default:
                throw new UnsupportedOperationException();
        }
    }

    @Override
    public Shape getShape(String shape) {
        throw new UnsupportedOperationException();
    }
}

package abstractFactory.retry_.design.factory;

import abstractFactory.retry_.design.impl.Color;
import abstractFactory.retry_.design.impl.Shape;
import abstractFactory.retry_.design.impl.shape.Circle;
import abstractFactory.retry_.design.impl.shape.Rectangle;
import abstractFactory.retry_.design.impl.shape.Square;

public class ShapeFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Shape getShape(String shape) {
        switch (shape) {
            case "CIRCLE": {
                return new Circle();
            }
            case "RECTANGLE": {
                return new Rectangle();
            }
            case "SQUARE": {
                return new Square();
            }
            default:
                throw new UnsupportedOperationException();
        }
    }
}

package abstractFactory.retry_.design.impl;

public interface Color {
    void fill();
}

package abstractFactory.retry_.design.impl;

public interface Shape {
    void draw();
}

package abstractFactory.retry_.design.impl.color;

import abstractFactory.retry_.design.impl.Color;

public class Blue implements Color {
    @Override
    public void fill() {
        System.out.println("filling blue!");
    }
}

package abstractFactory.retry_.design.impl.color;

import abstractFactory.retry_.design.impl.Color;

public class Green implements Color {
    @Override
    public void fill() {
        System.out.println("filling green!");
    }
}

package abstractFactory.retry_.design.impl.color;

import abstractFactory.retry_.design.impl.Color;

public class Red implements Color {
    @Override
    public void fill() {
        System.out.println("filling red!");
    }
}


package abstractFactory.retry_.design.impl.shape;

import abstractFactory.retry_.design.impl.Shape;

public class Circle implements Shape {
    @Override
    public void draw() {

    }
}

package abstractFactory.retry_.design.impl.shape;

import abstractFactory.retry_.design.impl.Shape;

public class Rectangle implements Shape {
    @Override
    public void draw() {

    }
}


package abstractFactory.retry_.design.impl.shape;

import abstractFactory.retry_.design.impl.Shape;

public class Square implements Shape {
    @Override
    public void draw() {

    }
}


抽象工厂模式,首先需要有一个抽象工厂,用于返回真正的工厂,
然后这些真正的工厂返回不同接口的各种实现;

5.工厂方法模式

先创建一个工厂,通过传入不同的标识符用于返回不同的服务类型,当然这些服务类型是统一实现了某个接口的;

package methodFactory.retry.store;

import java.util.Map;

public interface ICommodity {

    void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception;

}

package methodFactory.retry.store.impl;

import methodFactory.retry.store.ICommodity;

import java.util.Map;

/**
 * 第三方兑换卡
 */
public class CardCommodityService implements ICommodity {
    @Override
    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {
        System.out.println("发送第三方兑换卡");
    }
}

package methodFactory.retry.store.impl;

import methodFactory.retry.store.ICommodity;

import java.util.Map;

/**
 * 折扣券
 *
 * @author liyuan
 */
public class CouponCommodityService implements ICommodity {
    @Override
    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {
        System.out.println("发送折扣券");
    }
}

package methodFactory.retry.store.impl;

import methodFactory.retry.store.ICommodity;

import java.util.Map;

/**
 * 实物商品
 */
public class GoodsCommodityService implements ICommodity {
    @Override
    public void sendCommodity(String uId, String commodityId, String bizId, Map<String, String> extMap) throws Exception {
        System.out.println("发送实物商品");
    }
}

package methodFactory.retry;

import methodFactory.retry.store.ICommodity;
import methodFactory.retry.store.impl.CardCommodityService;
import methodFactory.retry.store.impl.CouponCommodityService;
import methodFactory.retry.store.impl.GoodsCommodityService;

public class StoreFactory {
    public ICommodity getCommodityService(Integer commodityType) {
        if (null == commodityType) {
            return null;
        }
        if (1 == commodityType) {
            return new CouponCommodityService();
        } else if (2 == commodityType) {
            return new GoodsCommodityService();
        } else if (3 == commodityType) {
            return new CardCommodityService();
        }
        throw new RuntimeException("服务类型不存在!");
    }
}

package methodFactory.retry.store;

import methodFactory.retry.StoreFactory;

import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws Exception {
        StoreFactory storeFactory = new StoreFactory();
        ICommodity commodityService = storeFactory.getCommodityService(2);
        commodityService.sendCommodity("1","2","3",new HashMap<>());
    }
}

结构型模式

1.适配器模式

对于一个类似的功能,学校A,B,C,D各实现了一遍,比如通过学号查询某个学生,他们的返回值虽然都是学生,但不同学校的开发人员对学生字段的定义可能有所差别,尽管信息大致都是相同的,那假如我要通过学生的学号以及其学校信息查询某个学校的学生;

``在这里插入图片描述

//AdapterFactory.java
	//通过不同学校名称返回不同的学校接口适配器
	public static SchoolServiceAdapter getSchoolService(String schoolName){
        if("A".equals(schoolName)){return new SchoolAServiceAdapter();}
        else if("B".equals(schoolName)){return new SchoolBServiceAdapter();}
        else if("C".equals(schoolName)){return new SchoolCServiceAdapter();}
        else {
            throw new UnsupportedOperationException(schoolName);
        }
    }
//适配器接口,用于适配各个学校实现的相似功能但不同方法名的方法
public interface SchoolServiceAdapter {
    public Member retrieveStudentById(Integer id);
}

public class SchoolAServiceAdapter implements SchoolServiceAdapter {
    private SchoolAServiceImpl schoolAService = new SchoolAServiceImpl();

    private Map<String,String> links = new HashMap<>();{
        links.put("uId","id");
        links.put("username","name");
        links.put("age","age");
    }


    @Override
    public Member retrieveStudentById(Integer id) {
        try {
            return (Member) MemberAdapter.adapter(schoolAService.getStudentById(id),Member.class,links);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException | NoSuchFieldException e) {
            throw new IllegalStateException(e);
        }
    }
}


public class SchoolBServiceAdapter implements SchoolServiceAdapter {

    private SchoolBServiceImpl schoolBService = new SchoolBServiceImpl();

    private Map<String,String> links = new HashMap<>();{
        links.put("id","id");
        links.put("name","name");
        links.put("age","age");
    }


    @Override
    public Member retrieveStudentById(Integer id) {
        try {
            return (Member) MemberAdapter.adapter(schoolBService.getStuById(id),Member.class,links);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException | NoSuchFieldException e) {
            throw new IllegalStateException(e);
        }
    }
}


public class SchoolCServiceAdapter implements SchoolServiceAdapter {
    private SchoolCServiceImpl schoolCService = new SchoolCServiceImpl();

    private Map<String,String> map = new HashMap<>();{
        map.put("uuid","id");
        map.put("usern","name");
        map.put("uage","age");
    }

    @Override
    public Member retrieveStudentById(Integer id)  {
        try {
            return (Member) MemberAdapter.adapter(schoolCService.getStudensByuuId(id),Member.class,map);
        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | NoSuchFieldException | InvocationTargetException e) {
            throw new IllegalStateException(e);
        }
    }
}



//由于该功能是通过学生学号返回学生的信息,但不同学校的开发人员对于不同学生实体类的设计不尽相同,但其信息大致是一致的,因此需要实现一个通用的用于承载学生信息的实体类

package adapter.adapter_try
class Member{
    var id: Int = 0
    var name: String=""
    var age: Int = 0
    override fun toString(): String {
        return "Member(id=$id, name='$name', age=$age)"
    }


}

package adapter.adapter_try;

public class Stu {
    private Integer id;
    private String name;
    private Integer age;

    public Integer getId() {
        return id;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Stu(Integer id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Stu() {
    }
}

package adapter.adapter_try;

public class Student {
    private Integer uId;
    private String username;
    private Integer age;


    public Integer getUId() {
        return uId;
    }

    public void setUId(Integer uId) {
        this.uId = uId;
    }

    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 "Student{" +
                "uId=" + uId +
                ", username='" + username + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

    public Student() {
    }

    public Student(Integer uId, String username, Integer age) {
        this.uId = uId;
        this.username = username;
        this.age = age;
    }

    public Student(Integer uId) {
        this.uId = uId;
    }
}


package adapter.adapter_try;

public class Students {
    private Integer uuid;
    private String usern;
    private Integer uage;


    public Integer getUuid() {
        return uuid;
    }

    public void setUuid(Integer uuid) {
        this.uuid = uuid;
    }

    public String getUsern() {
        return usern;
    }

    public void setUsern(String usern) {
        this.usern = usern;
    }

    public Integer getUage() {
        return uage;
    }

    public void setUage(Integer uage) {
        this.uage = uage;
    }

    @Override
    public String toString() {
        return "Students{" +
                "uuid=" + uuid +
                ", usern='" + usern + '\'' +
                ", uage=" + uage +
                '}';
    }

    public Students(Integer uuid, String usern, Integer uage) {
        this.uuid = uuid;
        this.usern = usern;
        this.uage = uage;
    }

    public Students() {
    }
}


package adapter.adapter_try;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class MemberAdapter {


    /**
     * 将输入的所有对象转换为Member
     *
     * @param original
     * @return
     */
    public static Object adapter(Object original, Class<?> target, Map<String, String> links) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        Object obj = target.getConstructor().newInstance();
        for (Map.Entry<String, String> entry : links.entrySet()) {
            String from = entry.getKey();
            String to = entry.getValue();
            Method method0 = original.getClass().getDeclaredMethod("get" + from.substring(0,1).toUpperCase(Locale.ROOT) + from.substring(1));
            Field f = target.getDeclaredField(to);
            Method method1 = target.getDeclaredMethod("set" + to.substring(0,1).toUpperCase(Locale.ROOT) + to.substring(1),f.getType());
            method1.invoke(obj,method0.invoke(original));
        }
        return obj;
    }
}
//调用


public class Main {
    public static void main(String[] args) {
        System.out.println(AdapterFactory.getSchoolService("D").retrieveStudentById(1));
    }
}

2.桥接模式

支付方式:
微信支付,支付宝支付
桥接
人脸,密码,指纹,瞳孔
//
支付方式:
游客,工作人员,老师,学生
桥接
qq登陆,微信登陆,密码登陆

public interface LoginMode {
    String login(Object...args);
}
public class PwdLoginMode implements LoginMode {
    @Override
    public String login(Object...args) {
        System.out.printf("账号密码登陆\n");
        return "password-login";
    }
}

public class QQLoginMode implements LoginMode {
    @Override
    public String login(Object...args) {
        System.out.printf("qq登陆\n");
        return "qq-login";
    }
}

public class WxLoginMode implements LoginMode {
    @Override
    public String login(Object...args) {
        System.out.printf("微信登陆\n");
        return "weixin-login";
    }
}
public class AnonymousUser extends User{
    @Override
    public String login(Object... args) {
        System.out.printf("匿名用户登陆\n");
        return "anonymous-user";
    }
}

public class Personnel extends User{
    @Override
    public String login(Object... args) {
        this.loginMode.login(args);
        System.out.println("职工登陆系统");
        return "personnel";
    }
}

public class Student extends User{
    @Override
    public String login(Object... args) {
        this.loginMode.login(args);
        System.out.printf("学生登陆系统");
        return "student";
    }
}


public class Teacher extends User{
    @Override
    public String login(Object... args) {
        this.loginMode.login(args);
        System.out.printf("老师登陆系统");
        return "teacher";
    }
}

public abstract class User {
    protected LoginMode loginMode;

    public void setLogin(LoginMode loginMode) {
        this.loginMode = loginMode;
    }

    public abstract String login(Object...args);
}
public class Main {
    public static void main(String[] args) {
        User user = new Student();
        user.setLogin(new QQLoginMode());
        user.login("admin","admin");
    }
}

3.组合模式

用于解决一系列简单逻辑节点或者扩展的复杂逻辑节点在不同结构组织下,对于外部的调用人人可以非常简单;
部分整体模式,用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
这种类型的设计模式属于结构型模式,创建了对象组的树形结构;

将对象组合成树形结构以表示“部分-整体”的层次结构;
组合模式使得用户对单个对象和组合对象的使用具有一致性;

package compose.compose_refractor;

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

public class Employee {
    private String name;
    private String dept;
    private int salary;
    private List<Employee> subordinates;

    public Employee(String name, String dept, int salary) {
        this.name = name;
        this.dept = dept;
        this.salary = salary;
        this.subordinates = new ArrayList<>();
    }

    public void add(Employee e){
        subordinates.add(e);
    }

    public void remove(Employee e){
        subordinates.remove(e);
    }

    public List<Employee> getSubordinates(){
        return subordinates;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", dept='" + dept + '\'' +
                ", salary=" + salary +
                ", subordinates=" + subordinates +
                '}';
    }
}
package compose.compose_refractor;

public class CompositePatternDemo {
    public static void main(String[] args) {
        Employee ceo_head = new Employee("liyuan0", "CEO_head", 100);
        Employee ceo1 = new Employee("liyaun1","CEO",150);
        Employee sales_head = new Employee("yuanxi0", "sales_head", 200);
        Employee sales1 = new Employee("yuanxi1", "sales", 250);
        Employee market_head = new Employee("ly", "market_head", 300);

        ceo_head.add(sales_head);
        ceo_head.add(ceo1);
        sales_head.add(sales1);
        ceo_head.add(market_head);

        for (Employee head : ceo_head.getSubordinates()) {
            System.out.println(head.toString());
        }


    }
}

4.装饰者模式

不改变原有的类;用于解决直接继承下因功能的不断横向扩展导致子类膨胀的问题,而使用装饰器模式会比直接继承显得更加灵活同时这样也就不再需要考虑子类的维护;
	1.抽象接口
	2.实现抽象接口
	3.定义抽象类并继承接口接口中的方法
	4.扩展装饰具体的实现逻辑

给我感觉就像是实现抽象类和接口之间的连接

package decorator.decorator_try;

public class ShapeDecoratorDemo {
    public static void main(String[] args) {
        RedShapeDecorator decorator = new RedShapeDecorator(new Rectangle());
        decorator.draw();
    }
package decorator.decorator_try;

public abstract class ShapeDecorator implements Shape{

   protected Shape shape;

   public ShapeDecorator(Shape shape) {
       this.shape = shape;
   }

   @Override
   public void draw() {
       shape.draw();
   }

}

5.外观模式

现在有需求,要求对某些接口做些处理,要求只有常住地址是一线城市的用户才可以访问该接口,简单的做法是直接修改代码,但难保以后会不会有来些什么限制,比如年龄大于18岁才可以访问,或账号充值过vip才可以访问,或白名单,黑名单等功能,因此很容易想到使用aop对这个接口做些限制;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Access {

    String message() default "";
}
@Configuration
@EnableConfigurationProperties(AccessProperties.class)
@ConditionalOnClass(AccessServiceImpl.class)
@ConditionalOnProperty(prefix = "access.list",value = "enabled",havingValue = "true",matchIfMissing = false)
public class AccessAutoConfiguration {

    @Autowired
    private AccessProperties accessProperties;


    @Bean
    public AccessServiceImpl listInfo() {
        String list = accessProperties.getListInfo();
        String[] strs = list.split(",");
        return new AccessServiceImpl(new HashSet<>(Arrays.asList(strs)));
    }

}
@ConfigurationProperties("access.list")
public class AccessProperties {
    private boolean enabled;
    private String listInfo;

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public String getListInfo() {
        return listInfo;
    }

    public void setListInfo(String listInfo) {
        this.listInfo = listInfo;
    }
}
public class AccessServiceImpl {

    private Set<String> accessList;

    public AccessServiceImpl(Set<String> accessList) {
        this.accessList = accessList;
    }

    public Set<String> getAccessList() {
        return accessList;
    }
}
@Component
@RestController
@Aspect
public class DoJointPoint {

    @Pointcut("@annotation(com.liyuan.www.design.door_.Access)")
    public void jp() {
    }

    @Autowired(required = false)
    private AccessServiceImpl accessList;


    @Around("jp()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] args = proceedingJoinPoint.getArgs();
        if (args.length>0&&accessList.getAccessList().contains(String.valueOf(args[0]))) {
            return proceedingJoinPoint.proceed();
        }
        Signature signature = proceedingJoinPoint.getSignature();
        Method method = proceedingJoinPoint.getTarget().getClass().getMethod(signature.getName(), ((MethodSignature) signature).getParameterTypes());
        Access annotation = method.getAnnotation(Access.class);
        String message = annotation.message();
        return JSON.toJSONString(message);
    }
}

6.享元模式

共享通用对象,这部分共享对象通常比较耗费内存或需要查询大量接口或使用数据库资源,因此统一抽离作为共享对象使用;可以理解为Spring的IOC容器,单例模式,共享同一对象;重点关注享元工厂模式的设计,在一些有大量重复对象可服用的场景下,使用此场景在服务端减少接口的调用;

public class ShareMap {
    private static Map<String, Object> ioc = new ConcurrentHashMap<>();


    public void put(String id, Object obj) {
        ioc.put(id, obj);
    }

    public Object get(String id) {
        return ioc.get(id);
    }
}

7.代理模式

代理某个类或某个接口

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SQLDialect {
    String value() default "";
}
public interface UserDao {

    @SQLDialect("select username from user where id = #{id}")
    String queryById(String id);


    @SQLDialect("insert into user(username,password) values(#{username},#{password})")
    String add(String username, String password);
}
public class MapperProxy {
    
    private static Pattern pattern = Pattern.compile("#\\{.*?\\}");

    public static <T> T getProxy(Class<?> interfaceMapper,Object proxyObject) {
        return (T) Proxy.newProxyInstance(MapperProxy.class.getClassLoader(), new Class[]{interfaceMapper}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke = method.invoke(proxyObject, args);
                System.out.println((String) invoke);
                SQLDialect annotation = method.getAnnotation(SQLDialect.class);
                String value = annotation.value();
                String sql = null;
                Matcher matcher = pattern.matcher(value);
                int index = 0;
                int groupCount = matcher.groupCount();
                while (matcher.find()) {
                    //sql = matcher.replaceFirst((String) args[index++]);
                    String key = matcher.group();
                    value = value.replace(key, (String) args[index++]);
                }
                return value;
            }
        });
    }
}
public class UserDaoImpl implements UserDao{
    @Override
    public String queryById(String id) {
        return "userDaoImpl -> queryById";
    }

    @Override
    public String add(String username, String password) {
        return "UserDaoImpl -> add";
    }
}

行为模式

1.责任链模式

解决一组服务中的先后执行处理关系;关键在于搭建链路的关联;简单了耦合也使对象关系更加清晰,而且外部的调用方并不需要关系责任链是如何进行处理的;

2.命令模式

以数据驱动的方式将命令对象使用构造函数的方式传递给调用者,调用者再根据相应的实现为命令执行提供操作方法;
面向接口编程:
将接口作为参数注入另一接口实现类中,从而可以动态选择接口实现,有点类似于策略模式;

package command.refractor_try.action;

public interface Action {
    void perform();
}
package command.refractor_try.action;

public class Drink implements Action{

    @Override
    public void perform() {
        System.out.println("drinking...");
    }
}
package command.refractor_try.action;

public class Eat implements Action{
    @Override
    public void perform() {
        System.out.println("eating...");
    }
}
package command.refractor_try.life;

public interface Life {

    void doSth();
}

package command.refractor_try.life;

import command.refractor_try.action.Action;

public class Human implements Life{
    private Action action;

    public Human(Action action) {
        this.action = action;
    }

    @Override
    public void doSth() {
        System.out.printf("人类表现:");
        action.perform();
    }
}
package command.refractor_try.life;

import command.refractor_try.action.Action;

public class Bacterium implements Life{
    private Action action;

    public Bacterium(Action action) {
        this.action = action;
    }

    @Override
    public void doSth() {
        System.out.printf("细菌表现L:");
        action.perform();
    }
}
package command.refractor_try.life;

import command.refractor_try.action.Action;

public class Animal implements Life{
    private Action action;

    public Animal(Action action) {
        this.action = action;
    }

    @Override
    public void doSth() {
        System.out.printf("动物表现:");
        action.perform();
    }
}
package command.refractor_try;

import command.refractor_try.action.Drink;
import command.refractor_try.action.Eat;
import command.refractor_try.life.Animal;
import command.refractor_try.life.Bacterium;
import command.refractor_try.life.Human;
import command.refractor_try.life.Life;

public class Main {
    public static void main(String[] args) {
        Life l = new Animal(new Drink());
        l.doSth();
        l = new Human(new Eat());
        l.doSth();
        l = new Bacterium(new Eat());
        l.doSth();
    }
}

3.中介者模式

使用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互;

package mediator;

import java.util.Date;

public class ChatRoom {
    public static void showMessage(User user,String message){
        System.out.println(new Date().toString()+"["+user.getName()+"] : "+message);
    }
}

package mediator;

public class User {
    private String name;

    public String getName() {
        return name;
    }

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

    public void setName(String name) {
        this.name = name;
    }
    public void sendMessage(String message){
        ChatRoom.showMessage(this,message);
    }
}

package mediator;

public class Main {
    public static void main(String[] args) {
        User u1 = new User("u1");
        User u2 = new User("u2");
        u1.sendMessage("你好!");
        u2.sendMessage("你也好!");

    }
}


4.备忘录模式

其实就是使用一个列表配置信息记录下来,设置一个指针指向当前最新配置文件信息,当配置修改时,保存修改的配置信息并将指针前移,当要回滚时,将指针回退即可,有点像git管理;也可以尝试将配置信息以及当前指针记录持久化;

package memorandum.design_;

import java.util.Date;

public class Memento {
    private Date date;
    private String username;
    private String password;
    private String level;

    public Memento(String username, String password, String level) {
        this.username = username;
        this.password = password;
        this.level = level;
        this.date = new Date();
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getLevel() {
        return level;
    }

    public void setLevel(String level) {
        this.level = level;
    }

    @Override
    public String toString() {
        return "Memento{" +
                "date=" + date +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", level='" + level + '\'' +
                '}';
    }
}

package memorandum.design_;

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

public class CareTaker {
    private int cursorIndex = -1;
    private List<Memento> mementos = new ArrayList<>();


    public void save(Memento memento){
        this.cursorIndex++;
        mementos.add(memento);
    }

    public Memento backward() {
        if (cursorIndex == 0) {
            return mementos.get(0);
        }
        cursorIndex--;
        return mementos.get(cursorIndex);
    }

    public Memento forward() {
        if (cursorIndex == (mementos.size() - 1)) {
            return mementos.get(mementos.size() - 1);
        }
        cursorIndex++;
        return mementos.get(cursorIndex);
    }

}


package memorandum.design_;

public class Main {
    public static void main(String[] args) {
        CareTaker careTaker = new CareTaker();
        careTaker.save(new Memento("liyuan1", "123456", "14"));
        careTaker.save(new Memento("liyuan2", "123", "15"));
        careTaker.save(new Memento("liyuan3", "456", "16"));
        System.out.println(careTaker.backward());
        System.out.println(careTaker.backward());
        System.out.println(careTaker.backward());
        System.out.println(careTaker.backward());
        System.out.println(careTaker.backward());
        System.out.println(careTaker.forward());
        System.out.println(careTaker.forward());
        System.out.println(careTaker.forward());
        System.out.println(careTaker.forward());


    }
}



5.观察者模式

发布,订阅,通知模式,常见例子是mq消息通知;
保证主流程不受辅流程影响,所以类视通知的事务一般使用异步方式;

package observer.retry_.listener;

public interface EventListener {
    void doEvent(String msg);
}

package observer.retry_.listener;

import javax.sound.midi.SoundbankResource;

public class MailEventListener implements EventListener {
    @Override
    public void doEvent(String msg) {
        System.out.println("此处触发邮件通知");
    }
}

package observer.retry_.listener;

public class MessageEventListener implements EventListener{
    @Override
    public void doEvent(String msg) {
        System.out.println("此处触发消息通知");
    }
}

package observer.retry_.listener;

public class PhoneEventListener implements EventListener {
    @Override
    public void doEvent(String msg) {
        System.out.println("此处触发手机通知");
    }
}
package observer.retry_;

import observer.retry_.listener.EventListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class EventManager {

    private Map<EventType, List<EventListener>> listenerMap = new ConcurrentHashMap<>();

    public void subscribe(EventType eventType, EventListener listener) {
        listenerMap.computeIfAbsent(eventType, l -> new ArrayList<>()).add(listener);
    }

    public void unsubscribe(EventType eventType, EventListener listener) {
        listenerMap.computeIfAbsent(eventType, l -> new ArrayList<>()).remove(listener);
    }

    public void notify(EventType eventType, String message) {
        List<EventListener> eventListeners = listenerMap.get(eventType);
        for (EventListener eventListener : eventListeners) {
            eventListener.doEvent(message);
        }
    }
}

package observer.retry_;

public enum EventType {
    EVENT1,
    EVENT2,
    EVENT3,
    EVENT4,
    EVENT5
}

package observer.retry_;

import observer.retry_.listener.MailEventListener;
import observer.retry_.listener.PhoneEventListener;

public class UserServiceImpl {
    private EventManager eventManager = new EventManager();

    {
        eventManager.subscribe(EventType.EVENT1, new MailEventListener());
        eventManager.subscribe(EventType.EVENT1, new PhoneEventListener());
    }

    ;

    public void register(String username, String password) {

        //it is obvious that this process is useless compared to the main process, recommend async;
        eventManager.notify(EventType.EVENT1, "用户注册 username:" + username + " password:" + password);

    }
}

package observer.retry_;

public class ApiTest {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.register("username","password");
    }
}

6.状态模式

对一个物体的多个状态的转换;
将各种状态的转换行为抽取出来作为一个接口,
各个物体实现仅与自己相关的状态转换接口;

package status.retry_;

public interface State<T> {
    // 液态 -> 固态
    default T solidify(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

    // 固态 -> 液态
    default T melt(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

    // 气态 -> 液态
    default T liquefaction(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

    // 液态 -> 气态
    default T vaporization(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

    // 固态 -> 气态
    default T sublimate(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

    //气态 -> 固态
    default T condensation(String id, Enum<StateEnum> currentState) {
        throw new UnsupportedOperationException();
    }

}

package status.retry_.state;

import status.retry_.AnObjectService;
import status.retry_.State;
import status.retry_.StateEnum;

public class Gaseous<T> implements State<T> {
    @Override
    public T liquefaction(String id, Enum<StateEnum> currentState) {
        System.out.println("气体液化");
        AnObjectService.getInstance().execState(id, currentState);
        return (T)"success";
    }

    @Override
    public T condensation(String id, Enum<StateEnum> currentState) {
        System.out.println("气体凝华");
        AnObjectService.getInstance().execState(id, currentState);
        return (T)"success";
    }
}

package status.retry_.state;

import status.retry_.AnObjectService;
import status.retry_.State;
import status.retry_.StateEnum;

public class Liquid<T> implements State<T> {
    @Override
    public T solidify(String id, Enum<StateEnum> currentState) {
        System.out.println("液体凝固");
        AnObjectService.getInstance().execState(id, currentState);
        return (T) "success";
    }

    @Override
    public T vaporization(String id, Enum<StateEnum> currentState) {
        System.out.println("液体汽化");
        AnObjectService.getInstance().execState(id, currentState);
        return (T) "success";
    }
}

package status.retry_.state;

import status.retry_.AnObjectService;
import status.retry_.State;
import status.retry_.StateEnum;

public class Solid<T> implements State<T> {

    @Override
    public T melt(String id, Enum<StateEnum> currentState) {
        System.out.println("固体熔化");
        AnObjectService.getInstance().execState(id, currentState);
        return (T) "success";
    }

    @Override
    public T sublimate(String id, Enum<StateEnum> currentState) {
        System.out.println("固态升华");
        AnObjectService.getInstance().execState(id, currentState);
        return (T) "success";
    }
}

package status.retry_;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AnObjectService {
    private AnObjectService() {
        activityMap.put("10001", StateEnum.SOLID);
    }

    public volatile static AnObjectService instance;

    private Map<String, Enum<StateEnum>> activityMap = new ConcurrentHashMap<>();

    public String execState(String activityId, Enum<StateEnum> state) {
        Enum<StateEnum> stateEnum = activityMap.get(activityId);
        if (stateEnum == null) {
            throw new UnsupportedOperationException("状态不存在");
        }
        activityMap.put(activityId, state);
        return "success";
    }


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

package status.retry_;

public enum StateEnum {
    LIQUID, SOLID, GASEOUS
}

package status.retry_;

import status.retry_.state.Gaseous;
import status.retry_.state.Liquid;
import status.retry_.state.Solid;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class StateHandler<T> implements State<T> {
    private Map<Enum<StateEnum>, State> stateMap = new ConcurrentHashMap<>();
    public StateHandler() {
        stateMap.put(StateEnum.SOLID, new Solid());
        stateMap.put(StateEnum.LIQUID, new Liquid());
        stateMap.put(StateEnum.GASEOUS, new Gaseous());
    }

    @Override
    public T solidify(String id, Enum currentState) {
        return (T) stateMap.get(currentState).solidify(id, currentState);
    }

    @Override
    public T melt(String id, Enum currentState) {
        return (T) stateMap.get(currentState).melt(id, currentState);
    }

    @Override
    public T liquefaction(String id, Enum currentState) {
        return (T) stateMap.get(currentState).liquefaction(id, currentState);
    }

    @Override
    public T vaporization(String id, Enum currentState) {
        return (T) stateMap.get(currentState).vaporization(id, currentState);
    }

    @Override
    public T sublimate(String id, Enum currentState) {
        return (T) stateMap.get(currentState).sublimate(id, currentState);
    }

    @Override
    public T condensation(String id, Enum currentState) {
        return (T) stateMap.get(currentState).condensation(id, currentState);
    }
}

7.策略模式

通过传入不同接口实现类,实现不同的功能;

package strategy.design;

import java.math.BigDecimal;

public interface ICouponDiscount<T> {
    BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice);
}

package strategy.design.impl;

import strategy.design.ICouponDiscount;

import java.math.BigDecimal;
import java.util.Map;

/**
 * 满减优惠
 */
public class MJCouponDiscount implements ICouponDiscount<Map<String, String>> {

    @Override
    public BigDecimal discountAmount(Map<String, String> couponInfo, BigDecimal skuPrice) {
        String x = couponInfo.get("x");
        String n = couponInfo.get("n");

        if (skuPrice.compareTo(new BigDecimal(x)) < 0) {
            return skuPrice;
        }
        BigDecimal discountAmount = skuPrice.subtract(new BigDecimal(n));
        if (discountAmount.compareTo(BigDecimal.ZERO) < 1) {
            return BigDecimal.ONE;
        }
        return discountAmount;
    }
}

package strategy.design.impl;

import strategy.design.ICouponDiscount;

import java.math.BigDecimal;

//n 元购
public class NYGCouponDiscount implements ICouponDiscount<Double> {
    @Override
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        return new BigDecimal(couponInfo);
    }
}

package strategy.design.impl;

import strategy.design.ICouponDiscount;

import java.math.BigDecimal;
import java.util.Map;

public class ZJCouponDiscount implements ICouponDiscount<String> {
    @Override
    public BigDecimal discountAmount(String couponInfo, BigDecimal skuPrice) {
        BigDecimal subtract = skuPrice.subtract(new BigDecimal(couponInfo));
        if(subtract.compareTo(BigDecimal.ZERO)<1){return BigDecimal.ONE;}
        return subtract;
    }
}

package strategy.design.impl;

import strategy.design.ICouponDiscount;

import java.math.BigDecimal;

//折扣
public class ZKCouponDiscount implements ICouponDiscount<Double> {
    @Override
    public BigDecimal discountAmount(Double couponInfo, BigDecimal skuPrice) {
        BigDecimal multiply = skuPrice.multiply(new BigDecimal(couponInfo)).setScale(2, BigDecimal.ROUND_HALF_UP);
        if (multiply.compareTo(BigDecimal.ONE) < 1) {
            return BigDecimal.ONE;
        }
        return multiply;
    }
}

package strategy.design;

import java.math.BigDecimal;

public class Context<T> {
    private ICouponDiscount<T> strategy;

    public void setStrategy(ICouponDiscount<T> strategy) {
        this.strategy = strategy;
    }

    public BigDecimal discountAmount(T couponInfo, BigDecimal skuPrice) {
        return strategy.discountAmount(couponInfo, skuPrice);
    }
}

package strategy.design;

import strategy.design.impl.NYGCouponDiscount;
import strategy.design.impl.ZJCouponDiscount;

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        Context<String> context = new Context<>();
        context.setStrategy(new ZJCouponDiscount());
        System.out.println(context.discountAmount("1.5", new BigDecimal("13.5")));

    }
}


8.模板模式

在抽象类中定义方法的执行顺序,并将抽象方法设定为仅有子类实现,但不设计独立访问的方法;
定义统一的结构,实现者仅需关心具体的业务逻辑实现;行为由父类控制,但具体由子类实现;

//AbstractInvoker.class
@Override
    public Result invoke(Invocation inv) throws RpcException {
        // if invoker is destroyed due to address refresh from registry, let's allow the current invoke to proceed
        if (destroyed.get()) {
            logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, "
                    + ", dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
        }

        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);
        if (attachment != null && attachment.size() > 0) {
            invocation.addAttachmentsIfAbsent(attachment);
        }
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (contextAttachments != null && contextAttachments.size() != 0) {
            /**
             * invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
             * because the {@link RpcContext#setAttachment(String, String)} is passed in the Filter when the call is triggered
             * by the built-in retry mechanism of the Dubbo. The attachment to update RpcContext will no longer work, which is
             * a mistake in most cases (for example, through Filter to RpcContext output traceId and spanId and other information).
             */
            invocation.addAttachments(contextAttachments);
        }
        if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {
            invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);


        try {
            return doInvoke(invocation);
        } catch (InvocationTargetException e) { // biz exception
            Throwable te = e.getTargetException();
            if (te == null) {
                return new RpcResult(e);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                return new RpcResult(te);
            }
        } catch (RpcException e) {
            if (e.isBiz()) {
                return new RpcResult(e);
            } else {
                throw e;
            }
        } catch (Throwable e) {
            return new RpcResult(e);
        }
    }
    
    protected abstract Result doInvoke(Invocation invocation) throws Throwable;

//以下是DubboInvoker.class
 @Override
    protected Result doInvoke(final Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation) invocation;
        final String methodName = RpcUtils.getMethodName(invocation);
        inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
        inv.setAttachment(Constants.VERSION_KEY, version);

        ExchangeClient currentClient;
        if (clients.length == 1) {
            currentClient = clients[0];
        } else {
            currentClient = clients[index.getAndIncrement() % clients.length];
        }
        try {
            boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
            if (isOneway) {
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                currentClient.send(inv, isSent);
                RpcContext.getContext().setFuture(null);
                return new RpcResult();
            } else if (isAsync) {
                ResponseFuture future = currentClient.request(inv, timeout);
                RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
                return new RpcResult();
            } else {
                RpcContext.getContext().setFuture(null);
                return (Result) currentClient.request(inv, timeout).get();
            }
        } catch (TimeoutException e) {
            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        } catch (RemotingException e) {
            throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

其中doInvoker()方法由DubboInvoker具体实现,而AbstractInvoker控制整体行为;
其中DubboInvoker中会具体与远程服务交互并获取返回结果;
类似的还有InjvmInvoker实现,该类也是实现了AbstarctInvoker方法,但其doInvoke具体是调用本地jvm中的服务;

9.访问者模式

在一个稳定的数据结构下,增加易变的业务访问逻辑。为增强扩展性,将这两部分的业务解耦的一种设计模式;

1.建立用户抽象类和抽象访问方法,再由不同的用户实现;-》老师和学生
2.建立访问者接口,用于不同人员的访问操作-》校长和家长
3.最终是对数据的看板建设,用于实现不同视角的访问结果输出;

在这里插入图片描述

package designPattern.visitor.user.impl;

import designPattern.visitor.user.User;
import designPattern.visitor.visitor.Visitor;

public class Student extends User {

    public Student(String name, String identity, String clazz) {
        super(name, identity, clazz);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public int ranking() {
        return (int) (Math.random() * 100);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", identity='" + identity + '\'' +
                ", clazz='" + clazz + '\'' +
                '}';
    }
}
package designPattern.visitor.user.impl;

import designPattern.visitor.user.User;
import designPattern.visitor.visitor.Visitor;

import java.math.BigDecimal;

public class Teacher extends User {

    public Teacher(String name, String identity, String clazz) {
        super(name, identity, clazz);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }


    public double entranceRatio() {
        return BigDecimal.valueOf(Math.random() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

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


package designPattern.visitor.user;

import designPattern.visitor.visitor.Visitor;

public abstract class User {
    public String name;
    public String identity;
    public String clazz;

    public User(String name, String identity, String clazz) {
        this.name = name;
        this.identity = identity;
        this.clazz = clazz;
    }

    public abstract void accept(Visitor visitor);
}
package designPattern.visitor.visitor.impl;

import designPattern.visitor.user.impl.Student;
import designPattern.visitor.user.impl.Teacher;
import designPattern.visitor.visitor.Visitor;

public class Parent implements Visitor {
    @Override
    public void visit(Student student) {
        System.out.println("家长访问 -> " + student.toString());
    }

    @Override
    public void visit(Teacher teacher) {
        System.out.println("家长访问 -> " + teacher.toString());
    }
}

package designPattern.visitor.visitor.impl;

import designPattern.visitor.user.impl.Student;
import designPattern.visitor.user.impl.Teacher;
import designPattern.visitor.visitor.Visitor;

public class Principal implements Visitor {
    @Override
    public void visit(Student student) {
        System.out.println("校长访问 -> " + student.toString());
    }

    @Override
    public void visit(Teacher teacher) {
        System.out.println("校长访问 -> " + teacher.toString()+"->"+teacher.entranceRatio());
    }

}
package designPattern.visitor.visitor;

import designPattern.visitor.user.User;
import designPattern.visitor.user.impl.Student;
import designPattern.visitor.user.impl.Teacher;

public interface Visitor {
    public void visit(Student student);

    public void visit(Teacher teacher);
}

package designPattern.visitor;

import designPattern.visitor.user.User;
import designPattern.visitor.user.impl.Student;
import designPattern.visitor.user.impl.Teacher;
import designPattern.visitor.visitor.Visitor;
import designPattern.visitor.visitor.impl.Parent;
import designPattern.visitor.visitor.impl.Principal;

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

public class DataView {
    List<User> userList = new ArrayList<>();

    public DataView() {
        userList.add(new Student("学生1", "理科班", "A班"));
        userList.add(new Student("学生2", "文科班", "B班"));
        userList.add(new Student("学生3", "理科班", "A班"));
        userList.add(new Student("学生4", "文科班", "B班"));
        userList.add(new Teacher("老师1", "高级教师", "文科班A班"));
        userList.add(new Teacher("老师2", "特级教师", "文科班B班"));
        userList.add(new Teacher("老师3", "普通教师", "理科班A班"));
    }

    public void show(Visitor visitor) {
        for (User user : userList) {
            user.accept(visitor);
        }
    }


    public static void main(String[] args) {
        DataView dataView = new DataView();
        dataView.show(new Parent());
        dataView.show(new Principal());
    }
}

10.迭代器模式

实现Iterable接口


package leet;

import java.util.Iterator;
import java.util.Scanner;

public class ListNode implements Iterable<ListNode> {
    private static Scanner input = new Scanner(System.in);
    public ListNode next;
    public int val;

    public ListNode(int data) {
        this.val = data;
    }

    public ListNode() {

    }

    public static ListNode create() {
        ListNode head = new ListNode(-1);
        ListNode ret = head;
        int tmp = -1;
        while ((tmp = input.nextInt()) != -1) {
            head.next = new ListNode(tmp);
            head = head.next;
        }
        return ret.next;
    }


    @Override
    public Iterator<ListNode> iterator() {
        final ListNode[] cur = {this};
        return new Iterator<ListNode>() {
            @Override
            public boolean hasNext() {
                return cur[0] != null;
            }

            @Override
            public ListNode next() {
                ListNode node = cur[0];
                cur[0] = cur[0].next;
                return node;
            }
        };
    }
}

package iterator.retry;

import leet.ListNode;

import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ListNode listNode = ListNode.create();
        Iterator<ListNode> iterator = listNode.iterator();
        while (iterator.hasNext()){
            ListNode next = iterator.next();
            System.out.println(next.val);
        }
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值