马士兵-23设计模式
马士兵-23设计模式
一、模式
1. 单例Singleton
8种写法,2种完美。
1-1. 应用场景
- 比如各种Manager
- 比如 各种Factory
- //饿汉式
- private static final Mgr01 INSTANCE=new Mgr01();//private main方法客户端 就无法new出多余对象实例
- private Mgr01(){};
- public static Mgr01 getInstance(){return INSTANCE;}
2. 策略Strategy
策略就是if分支逻辑的改写。
- Comparable
- Comparator
1.8之后接口里面必须有方法实现,为了支持lambda表达式。
- public class DogComparator implements Comparator<Dog>{
-
- public int compare(Dog o1, Dog o2) {
- return o1.food-o2.food;
- }
- }
- public class Sorter3<T> {
- /*通过泛型实现动态类型比较器的排序方法*/
- public void sort(T[] a,Comparator<T> comparator) {//不可能每种类型都要写一遍排序,所以要求要排序的类实现comparato方法,
- // 传进来的参数如果是Object接收参数,Object又没实现comparato,所以可以使用Comparable,里面实现了方法,
- // 方法里是compara(Object o),所以object要强所在的类的类型,再去比较
- for (int i = 0; i < a.length; i++) {
- int minPos=i;
- for (int j = i+1; j < a.length; j++) {
- minPos=comparator.compare(a[j],a[minPos])==-1?j:minPos;//第二步:调用比较器
- }
- swap(a,i,minPos);
- }
- }
- private void swap(T[] a, int i, int j) {
- T temp=a[i];
- a[i]=a[j];
- a[j]=temp;
- }
- }
- public class Main {
- public static void main(String[] args) {
- // int[] a={9,2,3,5,7,1,4};
- // Cat2[] a={new Cat2(3,3),new Cat2(5,5),new Cat2(1,1)};
- Dog[] a={new Dog(2),new Dog(3),new Dog(5),new Dog(0)};
- Sorter3 sorter=new Sorter3();
- sorter.sort(a,new DogComparator());
- System.out.println(Arrays.toString(a));
- }
- }
- //----------------------------------------------函数式
- public class Main {
- public static void main(String[] args) {
- // int[] a={9,2,3,5,7,1,4};
- // Cat2[] a={new Cat2(3,3),new Cat2(5,5),new Cat2(1,1)};
- Dog[] a={new Dog(2),new Dog(3),new Dog(5),new Dog(0)};
- Sorter3<Dog> sorter=new Sorter3();
- // sorter.sort(a,new DogComparator());
- sorter.sort(a,(o1,o2)->{return o1.food-o2.food;});
- System.out.println(Arrays.toString(a));
- }
- }
3. 第三第四工厂和抽象工厂Factory
3-1. 工厂系列
- 简单工厂
- 静态工厂
- 工厂方法
- 抽象工厂
- Spring IOC(控制翻转,动态注入)
3-2. 定义
- 任何可以产生对象的方法或类,都可以称之为工厂
- 单例也是一种工厂
- 不可咬文嚼字,死抠概念2
- 为什么有了new之后,还要有工厂
- 灵活控制2生产过程
- 权限,修饰,日志。。。
3-3. 举例
- 任意定义交通工具:继承Moveable
- public interface Moveable {
- void go();
- }
- public class Broom implements Moveable{
-
- public void go() {
- System.out.println("Broom在跑");
- }
- }
- public class Main
- {
- public static void main(String[] args) {
- Moveable m=new Broom();
- m.go();
- }
- }
- //-----------------------
- public class Car implements Moveable{
-
- public void go(){
- System.out.println("Car 在跑");
- }
- }
- 任意定制生产过程:使用Moveable XXFactory.create方法
- public class CarFacory {
- public Moveable createCar(){
- // 日志操作
- System.out.println("car的交通工具扩展工厂");
- return new Car();
- }
- }
- 任意定制产品一族
- /**
- * create-date:2022/6/28
- * author:guojia.ma
- * 工厂下调用实现就不需要在客户端new创建实例了,
- */
- public class Main {
- public static void main(String[] args) {
- ModernFactory f = new ModernFactory();
- Vehicle c = f.createVehicle();
- Weapon w = f.createWeapon();
- Food b = f.createFood();
- c.go();w.shoot();b.printName();
- }
- }
- public abstract class AbstractFactory {
- abstract Food createFood();
- abstract Vehicle createVehicle();
- abstract Weapon createWeapon();
- }
- public class AK47 extends Weapon{
-
- void shoot() {
- System.out.println("tuutututu");
- }
- }
- public class Bread extends Food{
-
- void printName() {
- System.out.println("wdm");
- }
- }
- public class Broom extends Vehicle{
-
- void go() {
- System.out.println("扫把飞");
- }
- }
- public class Car extends Vehicle{
-
- void go() {
- System.out.println("轿车 跑");
- }
- }
- public abstract class Food {
- abstract void printName();
- }
- public class MagicFactory extends AbstractFactory{
-
- Food createFood() {
- return new MushRoom();
- }
-
- Vehicle createVehicle() {
- return new Broom();
- }
-
- Weapon createWeapon() {
- return new MagicStrick();
- }
- }
- public class MagicStrick extends Weapon{
-
- void shoot() {
- System.out.println("电击");
- }
- }
- public class ModernFactory extends AbstractFactory{
-
- Food createFood() {
- return new Bread();
- }
-
- Vehicle createVehicle() {
- return new Car();
- }
-
- Weapon createWeapon() {
- return new AK47();
- }
- }
- /**
- * create-date:2022/6/27
- * author:guojia.ma
- * 三类:武器,食品,交通工具
- * 针对现代人:是AK47,Bread,Car(一个族的概念)
- * 针对魔法人: 是MagicBrick,MushRoom,Broom
- */
- public class MushRoom extends Food{
-
- void printName() {
- System.out.println("花蘑菇");
- }
- }
- public abstract class Vehicle {
- abstract void go();
- }
- public abstract class Weapon {
- abstract void shoot();
- }
在简单工厂使用了接口Moveable,而在抽象工厂用了抽象类Food;差异其实是语义的区别,比如Move是属性,可能还有其他用接口,后续可以多实现扩展;而Food是具体概念,但是不是具体面包还是什么,但是基本固定用抽象类做继承关系即可。
- 形容词用接口
- 名词用抽象类
工厂方法,产品好扩展;而产品族的扩展抽象工厂比较方便,但是需要该一堆抽象工厂(族的工厂,产品的工厂)的工厂方法实现。
3-4. 更好的解决方案
- spring ioc
- bean工厂
4. 第五第六门面-调停者Mediator(消息中间件)
对外叫门面Facade,对内叫调停者Mediator
5. 装饰器Decorator
5-1. 问题
- 坦克想加一个外壳显示
- 想加一个血条
- 想加一条尾巴
- 子弹想加一条尾巴
- 子弹想加一个外壳
如果用继承,不灵活,装饰和被装饰者之间耦合度太高,类爆炸。
很多模式不是语法有区别,很多都是语义上有区别:比如桥梁模式是两个线独立发展,而装饰者模式是一个线的装饰设计=》两个设计都可以从依赖关系的设计拆解=》用代码依赖关系的实现即可。所以语法很像
6. 第八责任链ChainOfResponsibility
(相比Proxy和reator模式难度次着)
案例代码Filter
6-1. 问题
- 在论坛中发表文章
- 后台经过信息处理才可以发表或者进入数据库
- /**
- * create-date:2022/6/28
- * author:guojia.ma
- * 责任链模式
- * 封装就是封装变化
- */
- public class Main {
- public static void main(String[] args) {
- Msg msg = new Msg();
- msg.setMsg("大家好:),<script>,欢迎访问top.guojia,大家都是996 ");
- // 处理msg
- /* String r = msg.getMsg();
- r=r.replace('<','[');
- r=r.replace('>',']');
- r=r.replaceAll("996","955");
- msg.setMsg(r);
- System.out.println(msg);*/
- /* new HTMLFilter().doFilter(msg);
- new SensitiveFilter().doFilter(msg);
- System.out.println(msg);*/
- // 把filter用list串起来
- /* ArrayList<Filter> filters = new ArrayList<>();
- filters.add(new HTMLFilter());
- filters.add(new SensitiveFilter());
- for (Filter f:filters
- ) {
- f.doFilter(msg);
- }
- System.out.println(msg);*/
- FilterChain fc=new FilterChain();
- /* fc.add(new HTMLFilter());
- fc.add(new SensitiveFilter());//add方法变函数式方式,fc的add实现增加返回值*/
- fc.add(new HTMLFilter()).add(new SensitiveFilter());
- // fc.doFilter(msg);
- // System.out.println(msg);
- // 两条链进行关联
- FilterChain fc2 = new FilterChain();
- fc2.add(new FaceFilter());
- fc.add(fc2);
- fc.doFilter(msg);
- System.out.println(msg);
- }
- }
- class Msg {
- String name;
- String msg;
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getMsg() {
- return msg;
- }
- public void setMsg(String msg) {
- this.msg = msg;
- }
-
- public String toString() {
- return "Msg{" +
- "name='" + name + '\'' +
- ", msg='" + msg + '\'' +
- '}';
- }
- }
- /*interface Filter{
- void doFilter(Msg m);
- }*/
- /*每個filter是否继续执行的判断*/
- interface Filter{
- boolean doFilter(Msg m);
- }
- class HTMLFilter implements Filter{
-
- public boolean doFilter(Msg m) {
- String r = m.getMsg();
- r=r.replace('<','[');
- r=r.replace('>',']');
- m.setMsg(r);
- return true;
- }
- }
- class SensitiveFilter implements Filter{
-
- public boolean doFilter(Msg m) {
- String r = m.getMsg();
- r=r.replaceAll("996","955");
- m.setMsg(r);
- return false;//如果出现敏感词就责任链往下停止执行
- }
- }
- class FaceFilter implements Filter{
-
- public boolean doFilter(Msg m) {
- String r = m.getMsg().replace(":)", "^v^");
- m.setMsg(r);
- return true;
- }
- }
- /*
- class FilterChain{
- List<Filter> filters=new ArrayList<>();
- */
- /* public void add(Filter f){
- filters.add(f);
- }*//*
- public FilterChain add(Filter f){
- filters.add(f);
- return this;
- }
- public void doFilter(Msg m){
- for (Filter f:filters
- ) {
- f.doFilter(m);
- }
- }
- }*/
- class FilterChain implements Filter{
- List<Filter> filters=new ArrayList<>();
- /* public void add(Filter f){
- filters.add(f);
- }*/
- public FilterChain add(Filter f){
- filters.add(f);
- return this;
- }
- public boolean doFilter(Msg m){
- for (Filter f:filters
- ) {
- if(!f.doFilter(m)){return false;}
- }
- return true;
- }
- }
责任链filter经典request,response的往回传链条
7. 第九Observer观察者(事件处理)
问题:小朋友睡醒哭,饿。
- /**
- * create-date:2022/6/28
- * author:guojia.ma
- * * 抽出事件,观察者的源(被观察者)
- * * 观察者的行为与被观察者及其事件类型是多对多关系
- */
- class Child{
- private boolean cry=false;
- private List<Observer> observers=new ArrayList<>();
- {
- observers.add(new Dad());
- observers.add(new Mum());
- observers.add(new Dog());
- }
- public boolean isCry(){return cry;}
- public void wakeUp(){
- cry=true;
- WakeUpEvent event = new WakeUpEvent(System.currentTimeMillis(), "bed",this);
- for (Observer o: observers
- ) {
- o.actionOnWakeUp(event);
- }
- }
- }
- abstract class Event<T>{
- abstract T getSource();
- }
- //事件类,fire event
- class WakeUpEvent extends Event<Child>{
- long timestamp;
- String loc;//location
- Child source;
- public WakeUpEvent(long timestamp, String loc, Child source){
- this.timestamp=timestamp;
- this.loc=loc;
- this.source=source;
- }
-
- Child getSource() {
- return source;
- }
- }
- interface Observer{
- void actionOnWakeUp(WakeUpEvent event);
- }
- class Dad implements Observer {
- public void feed(){
- System.out.println("dad feeding..");
- }
-
- public void actionOnWakeUp(WakeUpEvent event) {
- feed();
- }
- }
- class Mum implements Observer {
- public void hug(){
- System.out.println("Mum hug..");
- }
-
- public void actionOnWakeUp(WakeUpEvent event) {
- hug();
- }
- }
- class Dog implements Observer {
- public void wang(){
- System.out.println("dog wang..");
- }
-
- public void actionOnWakeUp(WakeUpEvent event) {
- wang();
- }
- }
- public class Main {
- public static void main(String[] args) {
- Child c=new Child();
- c.wakeUp();
- }
- }
Observer,Listener,Hook,Callback都是观察者
在很多系统中,Observer模式往往和责任链工程负责对于事件的处理,其中的某一个observer负责是否将事件进一步传递;所以看见event也多是观察者模式有以上几个观察者的关键字标识。
观察者的模式用在责任链中一般没有往回传的链处理。
8. 第十组合Composite
树状结构专用模式
- abstract class Node{
- abstract public void p();
- }
- class leafNode extends Node{
- String content;
- public leafNode(String content){this.content=content;}
-
- public void p() {
- System.out.println(content);
- }
- }
- class BranchNode extends Node{
- List<Node> nodes=new ArrayList<>();
- String name;
- public BranchNode(String name){this.name=name;}
-
- public void p() {
- System.out.println(name);
- }
- public void add(Node n){
- nodes.add(n);
- }
- }
- public class Main {
- public static void main(String[] args) {
- // tree(root);
- }
- static void tree(Node b,int depth){
- for (int i = 0; i < depth; i++) {
- System.out.print("--");
- }
- b.p();
- if(b instanceof BranchNode){
- for (Node n: ((BranchNode) b).nodes
- ) {
- tree(n,depth+1);
- }
- }
- }
- }
9. 第11flyweight(享元)
重复利用对象
- class Bullet{
- public UUID id= UUID.randomUUID();
- boolean living=true;
-
- public String toString() {
- return "Bullet{" +
- "id=" + id +
- ", living=" + living +
- '}';
- }
- }
- public class BulletPool {
- List<Bullet> bullets=new ArrayList<>();
- {
- for (int i = 0; i < 5; i++) {
- bullets.add(new Bullet());
- }
- }
- public Bullet getBullet(){
- for (int i = 0; i < bullets.size(); i++) {
- Bullet bullet = bullets.get(i);
- if(!bullet.living){return bullet;};
- }
- return new Bullet();
- }
- public static void main(String[] args) {
- BulletPool bp=new BulletPool();
- for (int i = 0; i < 10; i++) {
- Bullet b = bp.getBullet();
- System.out.println(b);
- }
- }
- }
10. 代理Proxy
- 静态代理
- 动态代理
- Spring AOP
benchamark查找性能差的点的测试用词。
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * 动态代理:时间计算,增加代理逻辑前后的处理方法
- */
- public class Tank implements Movable{
-
- public void move() {
- System.out.println("Tank moving clacla...");
- try {
- Thread.sleep(new Random().nextInt(10000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- Tank tank=new Tank();
- System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true");//生成代理类的字节码文件
- //reflection 反射,类的二进制字节码落进内存,通过字节码分析类的属性和方法。
- Movable m=(Movable) Proxy.newProxyInstance(Tank.class.getClassLoader()//被代理对象
- , new Class[]{Movable.class},//代理对象实现的接口数组 tank.class.getInsterfaces();
- new TimeProxy(tank) //代理对象实现接口的代理逻辑
- );
- m.move();//调用move方法走了代理逻辑invoke,这就是动态代理的神奇
- }
- }
- class TimeProxy implements InvocationHandler{
- Movable m;
- public TimeProxy(Movable m){this.m=m;}
- public void before(){
- System.out.println("method start before..");
- }
- public void after(){
- System.out.println("method end after...");
- }
- // getClass.getMethods[]:第一个参数proxy就是代理对象即m
-
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // System.out.println("method " + method.getName() + "start..");
- before();
- Object o = method.invoke(m, args);//m就是被代理对象(即tank实现了movable) move方法返回是空值,o就是空值
- // System.out.println("method " + method.getName() + "end!");
- after();
- return o;
- }
- }
- interface Movable{
- void move();
- }
动态代理的类文件:
asm包是直接操作二进制字节码文件。
有了asm就不需要源码,这也是java是动态语言(运行时修改代码)的本质。
所以只要符合class文件字节码存储要求,就可以跑在JVM上
kotlin,scala就是直接编译生成class文件跑在jvm里。JVM生态
10-1. jdk生成动态代理需要实现接口而有些不需要
- 如Instrement(调琴)的方式(java自带)不需要实现接口,钩子函数拦截器在落内存中的时候直接修改二进制码(要求完全了解二进制码)比asm的api更加强大。
- 还有cglib(底层是asm)生成要比jdk的反射生成简单很多:tank如果是final类不可以因为enhancer是继承tank(asm可以把final去掉)。
AOP:A就是Aspect 切
IOC+AOP
bean工厂+灵活装配+动态行为拼接,成就spring在java框架中的一哥位置
11. 13模式Iterator迭代器
容器及容器遍历场景
11-1. 需求
- 构建动态扩展的容器
- list.add()
- 数组的实现
- 链表的实现
数组vs链表:插入,删除,随机访问,扩展
- public class ArrayList_<E> implements Collection_<E>{
- E[] objects =(E[])new Object[10];
- private int index=0;
-
- public void add(E o) {
- if(index==objects.length){
- E[] newObjects =(E[])new Object[this.objects.length * 2];
- System.arraycopy(objects,0,newObjects,0,objects.length);
- objects=newObjects;
- }
- objects[index]=o;
- index++;
- }
-
- public int size() {
- return index;
- }
-
- public Iterator_<E> iterator() {
- return new ArrayListIterator();
- }
- private class ArrayListIterator implements Iterator_<E>{
- private int currentIndex=0;
-
- public boolean hasNext() {
- if(currentIndex>=index){return false;}
- return true;
- }
-
- public E next() {
- E o = objects[currentIndex];
- currentIndex++;
- return o;
- }
- }
- }
- public interface Collection_<E> {
- void add(E o);
- int size();
- Iterator_<E> iterator();
- }
- public interface Iterator_<E> {
- boolean hasNext();
- E next();
- }
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * 链表的迭代器实现简版
- */
- public class ListkedList_<E> implements Collection_<E>{
- Node head=null;
- Node tail=null;
- //目前容器中有多少个元素
- private int size=0;
- private class Node<E>{
- private E o;
- Node next;
- public Node(E o){this.o=o;}
- }
-
- public void add(E o) {
- Node n=new Node(o);
- n.next=null;
- if(head==null){
- head=n;
- tail=n;
- }
- tail.next=n;
- tail=n;
- size++;
- }
-
- public int size() {
- return size;
- }
-
- public Iterator_<E> iterator() {
- return new LinkedListIterator(head);
- }
- private class LinkedListIterator<E> implements Iterator_<E>{
- private Node next;
- private int index=0;
- public LinkedListIterator(Node head){
- // assert isPositionIndex(index);
- this.next=head;
- }
-
- public boolean hasNext() {
- if(index>=size){return false;}
- return true;
- }
-
- public E next() {
- E n=null;
- if(hasNext()){
- next = this.next.next;
- n=(E) next.o;
- index++;
- return n;
- }
- return null;
- }
- }
- }
- public class Main {
- public static void main(String[] args) {
- Collection_<String> list = new ListkedList_<>();
- for (int i = 0; i < 15; i++) {
- list.add(new String("s"+i));
- }
- System.out.println(list.size());
- /* Collection c = new LinkedList();
- for (int i = 0; i < 15; i++) {
- c.add(new String("s"+i));
- }*/
- // System.out.println(c.size());
- Iterator_<String> it=list.iterator();
- // Iterator it = c.iterator();
- while(it.hasNext()){
- String o = it.next();
- System.out.println(o);
- }
- }
- }
12. 14访问者visitor
在结构不变的情况下动态改变对于内部元素的动作。
- package top.guojia.mode.visitor;
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * 观察者模式
- */
- public class Computer {
- ComputerPart cpu=new Cpu();
- ComputerPart memory=new Memory();
- ComputerPart board=new Board();
- public void accept(Visitor v){
- this.cpu.accept(v);//接待来访者
- this.memory.accept(v);
- this.board.accept(v);
- }
- public static void main(String[] args) {
- PersonelVisitor p=new PersonelVisitor();
- new Computer().accept(p);
- System.out.println(p.totalPrice);
- }
- }
- abstract class ComputerPart{
- abstract void accept(Visitor v);
- abstract double getPrice();
- }
- class Cpu extends ComputerPart{
-
- void accept(Visitor v) {
- v.visitCpu(this);
- }
-
- double getPrice() {
- return 500;
- }
- }
- class Memory extends ComputerPart{
-
- void accept(Visitor v) {
- v.visitMemory(this);
- }
-
- double getPrice() {
- return 300;
- }
- }
- class Board extends ComputerPart{
-
- void accept(Visitor v) {
- v.visitBoard(this);
- }
-
- double getPrice() {
- return 100;
- }
- }
- interface Visitor{
- void visitCpu(Cpu cpu);
- void visitMemory(Memory memory);
- void visitBoard(Board board);
- }
- class PersonelVisitor implements Visitor{//个人类型的来访者
- double totalPrice=0.0;
-
- public void visitCpu(Cpu cpu) {
- totalPrice+=cpu.getPrice()*0.9;
- }
-
- public void visitMemory(Memory memory) {
- totalPrice+=memory.getPrice()*0.85;
- }
-
- public void visitBoard(Board board) {
- totalPrice+=board.getPrice()*0.95;
- }
- }
- class CorpVisitor implements Visitor{
- double totalPrice=0.0;
-
- public void visitCpu(Cpu cpu) {
- totalPrice+=cpu.getPrice()*0.8;
- }
-
- public void visitMemory(Memory memory) {
- totalPrice+=memory.getPrice()*0.8;
- }
-
- public void visitBoard(Board board) {
- totalPrice+=board.getPrice()*0.8;
- }
- }
访问者模式只针对结构固定的可以让访问者访问固定的结构,结构接受访问。
12-1. ASM
如果了解每个字节什么意思,应该读JAVA虚拟机规范。
JAVAP反编译class文件用汇编的方式展示
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * asm反编译javap底层逻辑:打印反编译内容的部分信息
- */
- public class ClassPrinter extends ClassVisitor {
- public ClassPrinter(){super(ASM4);}
-
- public void visit(int version,int access,String name,String signature,String superName,String[] interfaces){
- System.out.println(name + " extends " + superName + "{");
- }
-
- public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value){
- System.out.println(" " + name);
- return null;
- }
-
- public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions){
- System.out.println(" " + name + "()");
- return null;
- }
-
- public void visitEnd(){
- System.out.println("}");
- }
- public static void main(String[] args) throws IOException {
- ClassPrinter cp = new ClassPrinter();//访问者
- ClassReader cr=new ClassReader("java.lang.Runnable");//被访问者
- cr.accept(cp,0);
- }
- }
- //--写字节码文件
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * 写出字节码信息
- */
- public class ClassWriteTest {
- public static void main(String[] args) {
- ClassWriter cw = new ClassWriter(0);
- cw.visit(V1_5,ACC_PUBLIC+ACC_ABSTRACT+ACC_INTERFACE,
- "pkg/Comparable",null,"java/lang/Object",null);
- cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC,"LESS","I",null,-1).visitEnd();
- cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC,"EQUAL","I",null,0).visitEnd();
- cw.visitField(ACC_PUBLIC+ACC_FINAL+ACC_STATIC,"GREATER","I",null,1).visitEnd();
- cw.visitMethod(ACC_PUBLIC+ACC_ABSTRACT,"compareTo","(Ljava/lang/Object;)I",null,null).visitEnd();
- cw.visitEnd();
- byte[] b = cw.toByteArray();
- MyClassLoader myClassLoader=new MyClassLoader();
- Class c=myClassLoader.defineClass("pkg.Comparable",b);
- System.out.println(c.getMethods()[0].getName());
- }
- public class MyClassLoader extends ClassLoader{
- public Class defineClass(String name,byte[] b){return defineClass(name,b,0,b.length);}
- }
12-2. 使用asm做动态代理的案例
- /**
- * create-date:2022/6/29
- * author:guojia.ma
- * 使用asm做动态代理
- */
- public class ClassTransformerTest {
- public static void main(String[] args) throws Exception {
- ClassReader cr=new ClassReader(ClassPrinter.class.getClassLoader().getResourceAsStream("top/guojia/mode/visitor/asm/Tank.class"));
- ClassWriter cw = new ClassWriter(0);
- ClassVisitor cv=new ClassVisitor(ASM4,cw){
-
- public MethodVisitor visitMethod(int access,String name,String descriptor,String signature,String[] exceptions){
- MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
- //returen mv
- return new MethodVisitor(ASM4,mv) {
-
- public void visitCode() {
- visitMethodInsn(INVOKESTATIC,"TimeProxy","before","()V",false);
- super.visitCode();
- }
- };
- }
- };
- cr.accept(cv,0);//cr里是cv,cv里是cw形成一个链,cv就相当于访问了cr然后在修改cr的开始代码visitCode,在里面访问代理TimeProxy类的静态方法;然后cw访问新修改后cr的cv数据写到磁盘文件字节码文件
- byte[] b = cw.toByteArray();
- String path =(String) System.getProperties().get("user.dir");
- File f = new File(path + "/top/guojia/mode/visitor/asm/");
- f.mkdirs();
- FileOutputStream fos= new FileOutputStream(new File(path+"/top/guojia/mode/visitor/asm/Tank_0.class"));
- fos.write(b);
- fos.flush();
- fos.close();
- }
- }
13. 15Builder
构造复杂对象。和模板方法非常像,不过这里是表示构建复杂对象。
13-1. 解析
- 分离复杂对象的构建和表示
- 同样的构建过程可以创建不同的表示
- 无需记忆,自然使用。
- public class Person {
- int id;
- String name;
- int age;
- double weight;
- int score;
- Location loc;
- private Person(){}
- public static class PersionBuilder{
- Person p=new Person();
- public PersionBuilder basicInfo(int id,String name,int age){
- p.id=id;
- p.name=name;
- p.age=age;
- return this;
- }
- public PersionBuilder weight(double weight){
- p.weight=weight;
- return this;
- }
- public PersionBuilder score(int score){
- p.score=score;
- return this;
- }
- public PersionBuilder loc(String street,String roomNo){
- p.loc=new Location(street,roomNo);
- return this;
- }
- public Person build(){return p;}
- }
- }
- class Location{
- String street;
- String roomNo;
- public Location(String street,String roomNo){
- this.street=street;
- this.roomNo=roomNo;
- }
- }
14. 16Adapter(Wrapper)
接口转换器:A-B不能直接访问加个转换。
- 电压转接头
- java.io
- jdbc-odbc bridge(不是桥接模式)
- ASM transformer
- public class Main {
- public static void main(String[] args) {
- FileInputStream fis = new FileInputStream("c:/test.text");
- InputStreamReader isr = new InputStreamReader(fis);
- BufferedReader br = new BufferedReader(isr);
- String line = br.readLine();
- while(line!=null&&line.equals("")){
- System.out.println(line);
- }
- br.close();
- }
- }
14-1. 误区:
- 常见的Adapter类反而不是Adapter比如WindowAdapter,KeyAdapter
15. 17 Bridge
双维度扩展
15-1. 解析
- 分离抽象和具体
- 用聚合方式(桥)连接抽象与具体
15-1-1. 分三步实现:
- public class Book extends GiftImpl{
- }
- public class Flower extends GiftImpl{
- }
- public abstract class Gift {
- GiftImpl impl;//1.在Gift里面聚合了实现;2.形容词+名词(WildGift的类继承这个名词带实现的抽象类Gift3.名词具体实体(Flower)从实现GiftImpl继承。
- }
- public class GiftImpl {
- }
- public class WarmGift extends Gift{
- public WarmGift(GiftImpl impl){
- this.impl=impl;
- }
- }
- public class WildGift extends Gift{
- public WildGift(GiftImpl impl){
- this.impl=impl;
- }
- }
- public class GG {
- public void chase(MM mm){
- Gift g = new WarmGift(new Flower());
- give(mm,g);
- }
- public void give(MM mm, Gift g){
- System.out.println(g + "gived");
- }
- }
16. 18Command命令
- 封装命令
- 结合cor实现undo功能
16-1. 解析
- 别名:Action/Transaction 动作/事务
- 宏命令:command与?(组合composite)模式:好多命令组成
- 多次undo:comand与?(cor)模式 多次undo
- transaction回滚:command与?(memento)模式
- public abstract class Command {
- public abstract void doit();//run, exec意思一样
- public abstract void undo();
- }
- public class Content {
- String msg="hello everybody ";
- }
- public class InsertCommand extends Command{
- Content c;
- String strToInsert="http://www.guojia.ma.top";
- public InsertCommand(Content c){
- this.c=c;
- }
-
- public void doit() {
- c.msg=c.msg+strToInsert;
- }
-
- public void undo() {
- c.msg=c.msg.substring(0,c.msg.length()-strToInsert.length());
- }
- }
- public class Main
- {
- public static void main(String[] args) {
- Content c=new Content();
- InsertCommand insertCommand = new InsertCommand(c);
- insertCommand.doit();
- insertCommand.undo();
- System.out.println(c.msg);
- }
- }
17. 19prototype原型模式
Object.clone()
17-1. java中的原型模式
- 自带
- 实现原型模式需要实现标记型接口Cloneable
- 一般会重写clone方法
- 如果只是重写clone方法而没实现接口,调用时会报异常(需要1.实现接口2重写clone方法)
- 编译不报错,运行报错重写可以直接super.clone用Object系统native clone方法。
- 一般用于一个对象的属性已经确定,需要产生很多相同对象的时候
- 需要区分深克隆(引用类型需要再调用clone把引用的数据拷贝一份:字符串不需要如果是new串需要)与浅克隆(引用类型引用地址被拷贝)
- //深克隆
- public class Test {
- public static void main(String[] args) throws CloneNotSupportedException {
- Person p1 = new Person();
- Person p2 =(Person)p1.clone();
- System.out.println(p2.age + " " + p2.score);
- System.out.println(p2.loc);
- System.out.println(p1.loc == p2.loc);
- p1.loc.street="sh";//因为loc被深克隆所以p1,p2互不影响
- System.out.println(p2.loc);
- }
- }
- class Person implements Cloneable{
- int age=8;
- int score=100;
- Location loc=new Location("bj",22);
-
- public Object clone() throws CloneNotSupportedException{
- Person p=(Person) super.clone();
- p.loc=(Location)loc.clone();
- return p;
- }
- }
- class Location implements Cloneable{//没有可实现的方法所以快捷键不支持生成方法要手动实现clone的overwrite
- String street;
- int roomNo;
- public Location(String street,int roomNo){
- this.street=street;
- this.roomNo=roomNo;
- }
-
- public String toString() {
- return "Location{" +
- "street='" + street + '\'' +
- ", roomNo=" + roomNo +
- '}';
- }
-
- public Object clone() throws CloneNotSupportedException{
- return super.clone();
- }
- }
18. 20Memento(备忘录)与序列化
记录状态便于回滚。
18-1. 解析
- 记录快照(瞬时状态)
- 存盘
transient 透明的:序列化时丢弃对象
18-1-1. 实现序列化:
- 实体类的父类:implenments Serializable
- 接口:extends Serializable
19. 21模板TemplateMethod
钩子函数
19-1. 解析
其实一直在用
- paint(Graphics g)
- WindowListener
- windowClosing()
- windowXXX()
- ASM
- ClassVisitor
- public class Main {
- public static void main(String[] args) {
- F f=new C1();
- f.m();
- }
- }
- abstract class F{
- void m(){
- op1();
- op2();
- }
- abstract void op1();
- abstract void op2();
- }
- class C1 extends F{
-
- void op1() {
- System.out.println("op1");
- }
-
- void op2() {
- System.out.println("op2");
- }
- }
20. 22State状态模式
根据状态决定行为
- public abstract class MMState {
- abstract void smile();
- abstract void cry();
- abstract void say();
- }
- public class MM {
- String name;
- MMState state;
- public void smile(){
- state.smile();
- }
- public void cry(){
- state.cry();
- }
- public void say(){
- state.say();
- }
- }
- public class MMHappyState extends MMState{
-
- void smile() {
- System.out.println("HappySmile");
- }
-
- void cry() {
- }
-
- void say() {
- }
- }
- public class MMCryState extends MMState{
-
- void smile() {
- System.out.println("苦中2带笑");
- }
-
- void cry() {
- }
-
- void say() {
- }
- }
client的opration不需要扩展适合用state模式,否则就要把所有state子类都要实现opration的扩展,代码耦合度太高。
21. 23Intepreter解释器
动态脚本解析
21-1. 解释器模式的结构
- 抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
- 终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
- 非终结符表达式:文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
- 环境角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。
21-2. 优缺点
-
优:解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。
-
缺:但是,解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件;由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。
21-3. 代码
- //代碼還有報錯
- class Context {}
- abstract class Expression {
- public abstract Object interpreter(Context ctx);
- }
- class TerminalExpression extends Expression {
- public Object interpreter(Context ctx){
- return null;
- }
- }
- class NonterminalExpression extends Expression {
- public NonterminalExpression(Expression...expressions){
- }
- public Object interpreter(Context ctx){
- return null;
- }
- }
- public class Client {
- public static void main(String[] args){
- String expression = "";
- char[] charArray = expression.toCharArray();
- Context ctx = new Context();
- Stack stack = new Stack();
- for(int i=0;i<5;i++) {
- //进行语法判断,递归调用
- }
- }
- Expression exp = stack.pop();
- exp.interpreter(ctx);
- }
- }