JAVA种的设计模式:23种设计模式

创建模式

单例模式

只产生一个,不允许new,直接使用就对了。

public class SimpleFactory {

    public static SimpleFactory simpleFactory = new SimpleFactory();
    private SimpleFactory(){}
}

单例模式应用的场景一般发现在以下条件下:

  (1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

  (2)控制资源的情况下,方便资源之间的互相通信。如线程池等。

工厂方法模式

​​​​​​      优点:易理解,操作简单

      缺点:违反设计模式的ocp原则,即对外扩展,对修改关闭。增加新功能时需要进行更多的代码修改。

public class SimpleFactory {

    /**
     * 这里的话由于简单就使用Object  string 来代替,便于理解!!!!!
     * 实际中可以声明一个父类 Parent ,两个子类 Son1、Son2 继承自Parent
     * 返回Parent   ,  product1  换成son1 ,product2 换成 parent2
     */
    Object getProduct(String a){
        if("a".equals(a)){
            return "product1";
        }else if("b".equals(a)){
            return "product2";
        }
        return null;
    }
}

结果就是,如果生了第三个,就得 新建son3,然后修改这个getProduct 方法,增加 if 和return son3。

抽象工厂

public class SimpleFactory {

    public static void main(String[] args) {
        OnlineSale onlineSale = new PhoneFactory();  //重点在这一行。 
OnlineSale 接口工厂, PhoneFactory 实现 其中的方法,
返回的类型只要是对应方法的返回类型的 子类

        Apple apple = onlineSale.getApple();
        apple.createPhone();

        Huawei huawei = onlineSale.getHuawei();
        huawei.createCpu();

        Vivo vivo = onlineSale.getVivo();
        vivo.createMusic();

    }

}

interface Apple{
    void createPhone();
}
class AppleLine implements Apple{
    public void createPhone() {System.out.println("组装手机流水线");}
}
interface Huawei{
    void createCpu();
}
class HuaweiLine implements Huawei{
    public void createCpu() {
        System.out.println("生产CPU流水线");
    }
}
interface Vivo{
    void createMusic();
}
class VivoLine implements Vivo{
    public void createMusic() {
        System.out.println("生产音乐流水线");
    }
}
interface OnlineSale{
    Apple getApple();
    Vivo getVivo();
    Huawei getHuawei();
}
class PhoneFactory implements OnlineSale {
    @Override
    public Apple getApple() {
        return new AppleLine();
    }

    @Override
    public Vivo getVivo() {
        return new VivoLine();
    }

    @Override
    public Huawei getHuawei() {
        return new HuaweiLine();
    }
}

不关注 HuaweiLine、VivoLine、AppleLine  这些类。重点在于 OnlineSale 接口 和其中的方法。然后进行  OnlineSale 接口的实现,可以有淘宝、京东、亚马逊的实现。  如果方法中返回需要对象,只要实现对应方法的接口类就可以了,可以有华北线、华南生产线、东北生产线。

抽象工厂模式的优点

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

抽象工厂模式的缺点

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

适用场景

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点

建造者模式:

应用场景: 需要生成的对象具有复杂的内部结构、需要生成的对象内部属性本身相互依赖、与不可变对象配合使用

优点:建造者独立,易扩展; 便于控制细节风险。

这种比较复杂,建议直接看第二种


public class SimpleFactory {

    public static void main(String[] args) {

        School school = new EnglishSchool();
        Studen studen = new Studen(school);
        Person person = studen.introduce("张三","17","男");
        System.out.println(person);
    }

}

interface School{
    void setSchool(String name);
    void setClass(String name);
    void setScore(String name);

    Person duce();
}

class EnglishSchool implements School{
    private String school;
    private String score;
    private String classs;

    @Override
    public void setSchool(String name) {
        this.school = name;
    }

    @Override
    public void setClass(String classs) {
        this.classs = classs;
    }

    @Override
    public void setScore(String score) {
        this.score = score;
    }

    @Override
    public Person duce() {
        return new Person(classs,score,school);
    }
}

class Studen{
    private School studySchool;

    public Studen(School school){
        this.studySchool = school;
    }

    Person introduce(String classs,String score,String school){
        studySchool.setClass(classs);
        studySchool.setSchool(school);
        studySchool.setScore(score);
        return studySchool.duce();
    }

}

class Person{
    private String school;
    private String score;
    private String classs;
    public Person(String classs,String score,String school){
        this.classs = classs;
        this.score = score;
        this.school = school;
    }

    @Override
    public String toString() {
        return "Person{" +
                "school='" + school + '\'' +
                ", score='" + score + '\'' +
                ", classs='" + classs + '\'' +
                '}';
    }
}

第二种 


public class v2 {
    public static void main(String[] args) {
        //重点
        new Person2.FinalPerson().setSchool("英文学校").setClass("二年级").setScore("90");
        new Person2.FinalPerson().setSchool("数学学校").setClass("二年级");
    }
}


class Person2{
    private final String school;
    private final String score;
    private final String classs;

    static class FinalPerson{
        private String school;
        private String score;
        private String classs;

        public FinalPerson setSchool(String school){
            this.school = school;
            return this;
        }
        public FinalPerson setScore(String score){
            this.score = score;
            return this;
        }
        public FinalPerson setClass(String classs){
            this.classs = classs;
            return this;
        }

        Person2 getPerson(){
            return new Person2(this.classs,this.score,this.school);
        }
    }

    private Person2(String classs,String score,String school){
        this.classs = classs;
        this.score = score;
        this.school = school;
    }

    @Override
    public String toString() {
        return "Person{" +
                "school='" + school + '\'' +
                ", score='" + score + '\'' +
                ", classs='" + classs + '\'' +
                '}';
    }
}

原型模式

指原型实例指定创建的对象的种类,并且通过拷贝这些原型创建新的对象。

应用场景:当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式

优点:可以不耦合具体类的情况下克隆对象,避免重复的初始化代码、更方便的构建复制对象


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

        Person2 p2 = new Person2("二年级","90","体育学院");
        System.out.println(p2);
        Person2 copyP2 = p2.clone(); //复制原型对象
        System.out.println(copyP2);
    }
}


class Person2 implements Cloneable{
    private String school;
    private String score;
    private String classs;

    @Override
    protected Person2 clone() throws CloneNotSupportedException {
//        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
////        try(ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);){
////            oos.writeObject(this);
////        }catch (Exception e){
////            e.printStackTrace();
////        }
////        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
////        try(ObjectInputStream oos = new ObjectInputStream(byteArrayInputStream);){
////            Person2 person2 = (Person2)oos.readObject();
////
////            System.out.println(person2);
////        }catch (Exception e){
////            e.printStackTrace();
////        }
        return (Person2)super.clone();
    }

    public Person2(String classs,String score,String school){
        this.classs = classs;
        this.score = score;
        this.school = school;
    }

    @Override
    public String toString() {
        return this.hashCode() + " : Person{" +
                "school='" + school + '\'' +
                ", score='" + score + '\'' +
                ", classs='" + classs + '\'' +
                '}';
    }
}
例如 ArrayList 中clone。  这种模式的拷贝是浅拷贝,非深度拷贝。

享元模式

运用共享技术有效地支持大量细粒度的对象。

例如常量池对象,spring 管理的对象,class loader。 已经有的对象就不用重新new,直接取出来使用。

优点:如果系统有大量类似的对象,可以节省大量的内存及CPU资源


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

        School2 school2 = new School2(SchoolFactory.getPerson("小朋友","80","学前班"),"英语学校");
        School2 school3 = new School2(SchoolFactory.getPerson("小朋友","80","学前班"),"英语学校");

    }
}

class SchoolFactory{
    private static Map<String,Person2> map = new ConcurrentHashMap<>();
    public static Person2 getPerson(String name,String score,String classs){
        if(map.containsKey(name)){
            return map.get(name);
        }
        Person2 p2 = new Person2(score,classs);
        map.put(name,p2);
        return p2;
    }
}

class School2{
    private Person2 person2;
    private String name;
    public School2(Person2 person2,String name){
        this.name = name;
        this.person2 = person2;
    }
}

class Person2{
    private final String score;
    private final String classs;

    public Person2(String classs,String score){
        this.classs = classs;
        this.score = score;
    }

    public String getScore() {
        return score;
    }

    public String getClasss() {
        return classs;
    }

    @Override
    public String toString() {
        return this.hashCode() + " : Person{" +
                ", score='" + score + '\'' +
                ", classs='" + classs + '\'' +
                '}';
    }
}

门面模式:

为子系统中的一组接口提供一个一致的接口,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用

应用场景:

1.当你需要使用复杂子系统的有限但直接的接口时,请使用Facade模式

2.当你想要将子系统组织成层时,请使用Facade。

优点:简化客户端的调用。


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

    }
}

class EnglishClass{
    Facade facade = new Facade();
    public void intorduce(){
        facade.study();
    }
}
class MathClass{
    Facade facade = new Facade();
    public void intorduce(){
        facade.study();
    }
}
class Facade{
    Studen1 studen1 = new Studen1();
    Studen2 studen2 = new Studen2();
    Studen3 studen3 = new Studen3();

    public void study(){
        studen1.s1();
        studen2.s2();
        studen3.s3();
    }
}

class Studen1{
    public void s1(){
        System.out.println(" i am s1");
    }
}
class Studen2{
    public void s2(){
        System.out.println(" i am s2");
    }
}
class Studen3{
    public void s3(){
        System.out.println(" i am s3");
    }
}

适配器模式

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类一起工作。

对接口污染较多,会产生很多不需要的方法

应用场景:

1.当你希望使用某些现有类,但其接口与你其它代码不兼容时,请使用适配器。

2.当你希望重用几个现有的子类,这些子类较少一些不能添加到超类中的公共功能时,请使用该模式。

优点:符合单一职责原则、符合开闭原则(对修改关闭,对扩展开放)。

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

    }
}

class Adaptee{
    public int output220v(){
        return 220;
    }
}

interface Target{
    int output5v();
}
class Adapter extends Adaptee implements Target{

    @Override
    public int output5v() {
        int i = output220v();
        if(i > 5){
            i = 5;
        }
        return i;
    }
}

装饰者模式 Decorator

在不改变原有对象的基础上,将功能附加到对象上

应用场景: HttpServletRequestWrapper、HttpServletResponseWrapper

扩展一个类的功能或给一个类添加附加职责

优点:

1.不改变原有对象的情况下给一个对象扩展功能

2.使用不同的组合可以实现不同的效果

3.符合开闭原则(对扩展开放,对修改关闭)


public class v2 {
    public static void main(String[] args) throws Exception {
        Component old = new ConcreteComponent();
        old.operation();

        Component news = new ConrateDecorator1(new ConcreteComponent());
        news.operation();

        Component news2 = new ConrateDecorator2(news);
        news2.operation();


    }
}
interface Component{
    void operation();
}
class ConcreteComponent implements Component{
    @Override
    public void operation() {
        System.out.println("拍照");
    }
}
abstract class Decorator implements Component{
    Component component;
    public Decorator(Component component){
        this.component = component;
    }
}
class ConrateDecorator1 extends Decorator{
    public ConrateDecorator1(Component component){
        super(component);
    }
    @Override
    public void operation() {
        component.operation();
        System.out.println(" 开启美颜");
    }
}
class ConrateDecorator2 extends Decorator{
    public ConrateDecorator2(Component component){
        super(component);
    }
    @Override
    public void operation() {
        component.operation();
        System.out.println(" 开启瘦脸");
    }
}

策略模式 strategy,对某一种行为进行封装,可以根据需求进行后期对应的策略变换。

定义了算法族,分别封装起来,让他们之间可以互相替换,此模式的变花独立于算法的使用者。

方式一(方式二可能会更便于理解):

public static void main(String[] args) throws Exception {
        Zombie zombie = new NormalZombie();
        zombie.display();
        zombie.attack();
        zombie.move();

        Zombie zombie1 = new FlagZombie(new DumpMove(),new HitAttack());
//        Zombie zombie1 = new FlagZombie();
//        zombie1.setAttackable(new HitAttack());
        zombie1.display();
        zombie1.attack();
        zombie1.move();
}
interface Moveable{
    void move();
}
interface Attackable{
    void attack();
}

abstract class Zombie{
    public abstract void display();
    Moveable moveable;
    Attackable attackable;
    abstract void move();
    abstract void attack();

    public Zombie(Moveable moveable,Attackable attackable){
        this.moveable = moveable;
        this.attackable = attackable;
    }
    public Moveable getMoveable() {
        return moveable;
    }
    public void setMoveable(Moveable moveable) {
        this.moveable = moveable;
    }
    public Attackable getAttackable() {
        return attackable;
    }
    public void setAttackable(Attackable attackable) {
        this.attackable = attackable;
    }
}

class NormalZombie extends Zombie{
    public NormalZombie(){super(new StepByStepMove(),new BiteAttack());}
    public NormalZombie(Moveable moveable,Attackable attackable){
        super(moveable,attackable);
    }
    @Override
    public void display() {
        System.out.println("普通僵尸");
    }
    @Override
    void move() {
        moveable.move();
    }
    @Override
    void attack() {
        attackable.attack();
    }
}
class FlagZombie extends Zombie{
    public FlagZombie(){super(new StepByStepMove(),new BiteAttack());}
    public FlagZombie(Moveable moveable,Attackable attackable){
        super(moveable,attackable);
    }
    @Override
    public void display() {
        System.out.println("旗手僵尸");
    }
    @Override
    void move() {
        moveable.move();
    }
    @Override
    void attack() {
        attackable.attack();
    }
}
class StepByStepMove implements Moveable{
    @Override
    public void move() {
        System.out.println("一步一步走");
    }
}
class DumpMove implements Moveable{
    @Override
    public void move() {
        System.out.println("跳舞");
    }
}
class BiteAttack implements Attackable{
    @Override
    public void attack() {
        System.out.println("咬");
    }
}
class HitAttack implements Attackable{
    @Override
    public void attack() {
        System.out.println("用头撞");
    }
}

方式二:

模板方法模式 Template Method

定义一个操作的算法骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

abstract class AbstractClass{
    public void opertion(){
        System.out.println("  pre ....");
        System.out.println(" find file");
        System.out.println("  step 2");
        templateMethod();
    }
    abstract protected  void templateMethod();
}
class SubClass extends AbstractClass{
    @Override
    protected void templateMethod() {
        System.out.println("  sub  class");
    }
}
class SubClassTwo extends AbstractClass{
    @Override
    protected void templateMethod() {
        System.out.println("  subTwo  class");
    }
}
public static void main(String[] args) throws Exception {
        AbstractClass abstractClass = new SubClass();
        abstractClass.opertion();

        AbstractClass abs = new SubClassTwo();
        abs.opertion();
}

观察者模式 Observer

定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖着都会收到通知并更新

应用场景:当更改一个对象的状态可能需要更改其它对象,并且实际的对象集事先未知或动态更改时,请使用观察者模式。

优点:符合对扩展开放,对修改关闭原则。 可以在运行时建立对象之间的关系

class Suject{
    List<Observer> list = new ArrayList<>();
    public void addObserver(Observer observer){
        list.add(observer);
    }
    public void remove(Observer observer){
        list.remove(observer);
    }
    public void notifyObserver(Object o){
        for(Observer observer1 : list){
            observer1.update(o);
        }
    }
}
interface Observer{
    void update(Object object);
}
class Task1 implements Observer{
    @Override
    public void update(Object object) {
        System.out.println(" received" + object);
    }
}
class Task2 implements Observer{
    @Override
    public void update(Object object) {
        System.out.println(" Task2 received" + object);
    }
}

Suject suject = new Suject();
        Task1 task1 = new Task1();
        Task2 task2 = new Task2();
        suject.addObserver(task1);
        suject.addObserver(task2);

        suject.notifyObserver(" 开始通知");
        System.out.println("--------------------");
        suject.remove(task1);
        suject.notifyObserver("重新通知");

责任链模式: Chain Of Responsibility

为请求创建了一个接收者对象的链

应用场景:一个请求的处理需要多个对象当中的一个或几个协作处理

优点:请求的发送者和接收者解耦

可以控制执行顺序

符合开闭原则和单一职责原则

class Request{
    private boolean login;
    private boolean frequent;
    private boolean isPermits;
    private boolean sitiWords;
    private String requestBody;
    private Request(boolean login,boolean frequent,boolean isPermits,
                    boolean sitiWords){
        this.login = login;
        this.frequent = frequent;
        this.isPermits = isPermits;
        this.sitiWords = sitiWords;
    }
    static class RequestBuilder{
        private boolean login;
        private boolean frequent;
        private boolean isPermits;
        private boolean sitiWords;

        RequestBuilder loginM(boolean isPermits){
            this.login = login;
            return this;
        }
        RequestBuilder frequentM(boolean frequent){
            this.frequent = frequent;
            return this;
        }
        RequestBuilder isPermitsM(boolean isPermits){
            this.isPermits = isPermits;
            return this;
        }
        RequestBuilder sitiWordM(boolean sitiWords){
            this.sitiWords = sitiWords;
            return this;
        }
        public Request build(){
            Request request = new Request(login,frequent,isPermits,sitiWords);
            return request;
        }
    }
    public boolean isLogin(){return login;}
    public boolean isFrequent(){return frequent;}
    public boolean isPermits(){return isPermits;}
    public boolean isSitiWords(){return sitiWords;}
}
abstract class Handler{
    Handler next;
    public Handler(Handler next){
        this.next = next;
    }
    public Handler getNext() {
        return next;
    }
    public void setNext(Handler next) {
        this.next = next;
    }
    abstract boolean process(Request request);
}
class RequestFrequentHandler extends Handler{
    public RequestFrequentHandler(Handler next){
        super(next);
    }
    @Override
    boolean process(Request request) {
        System.out.println("访问频率控制");
        if(request.isFrequent()){
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            }else{
                return true;
            }
        }
        return false;
    }
}
class LoginHandler extends Handler{
    public LoginHandler(Handler next){
        super(next);
    }
    @Override
    boolean process(Request request) {
        System.out.println("是否登录");
        if(request.isLogin()){
            Handler next = getNext();
            if(next == null){
                return true;
            }
            if(!next.process(request)){
                return false;
            }else{
                return true;
            }
        }
        return false;
    }
}

Request request = new Request.RequestBuilder().frequentM(true).loginM(true).build();
//        Request request = new Request.RequestBuilder().frequentM(true).loginM(false).build();
        RequestFrequentHandler requestHeader = new RequestFrequentHandler(new LoginHandler(null));
        if(requestHeader.process(request)){
            System.out.println(" 正常放行");
        }else{
            System.out.println("不通过");
        }

桥接模式

https://www.bilibili.com/video/BV1Ak4y1R7jM?from=search&seid=15289757876957547587

无论是类型还是品牌两个方向的扩展,都不会影响另一方,但是双方可以通过中间点进行连接起来

interface Brand{
    void info();
}
class Lenovo implements Brand{
    @Override
    public void info() {
        System.out.print("联想");
    }
}
class Apple implements Brand{
    @Override
    public void info() {
        System.out.print("苹果");
    }
}
abstract class Computer{
    protected Brand brand;

    public Computer(Brand brand) {
        this.brand = brand;
    }
    public  void comInfo(){
        brand.info();
    }
}
class DeskTop extends Computer{
    public DeskTop(Brand brand) {
        super(brand);
    }

    @Override
    public void comInfo() {
        super.comInfo();
        System.out.println("台式机");
    }
}
class LapTop extends Computer{
    public LapTop(Brand brand) {
        super(brand);
    }

    @Override
    public void comInfo() {
        super.comInfo();
        System.out.println("笔记本");
    }
}
Computer computer = new LapTop(new Apple());
        computer.comInfo();

        Computer computer1 = new DeskTop(new Lenovo());
        computer1.comInfo();

桥接点: Computer 类

代理模式

静态代理

https://www.bilibili.com/video/BV1mc411h719

在代理的过程中,可以增加附加操作

优点:

可以使真实角色操作更加纯粹,不用去关注一些公共的业务

公共也就交给代理角色,实现了业务的分工

公共业务发生扩展的时候,方便集中管理

缺点: 一个真实角色久会产生一个代理角色,代码量会翻倍

interface Rent{
    void rent();
}
class Host implements Rent {
    @Override
    public void rent() {
        System.out.print("出租房子");
    }
}
class Proxy implements Rent{
    private Host host;

    public Proxy(){}
    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        host.rent();
        fare();
    }
    //支持扩展的方法
    public void seeHouse(){
        System.out.println("带你看房子");
    }
    public void fare(){
        System.out.println("收费");
    }
}

动态代理

jdk动态代理

interface IGame {
    void login();
    void playLOL();
}
class IGamePlayer implements IGame {
    private String name;
    public IGamePlayer(String name) {
        this.name = name;
    }
    @Override
    public void login() {
        System.out.println(name+"登录游戏");
    }
    @Override
    public void playLOL() {
        System.out.println(name+"赢下了一局英雄联盟,获得了100金币");
    }
}
//通知(这个例子用来统计登录接口的耗时)
interface IAdvice {
    void execute();
}
//前置通知
class BeforeAdvice implements IAdvice {
    @Override
    public void execute() {
        System.out.println("执行前时间:"+System.currentTimeMillis());
    }
}
//后置通知
class AfterAdvice implements IAdvice {
    @Override
    public void execute() {
        System.out.println("执行后时间:"+System.currentTimeMillis());
    }
}
class DynamicProxy{
    private Object target;
    public DynamicProxy(Object target) {
        this.target = target;
    }
    public Object getInstance(ClassLoader classLoader, Class[] interfaces){
        return Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //连接点
                if (method.getName().startsWith("login")){
                    new BeforeAdvice().execute();
                }
                Object objec=method.invoke(target,args);
                if (method.getName().startsWith("login")){
                    new AfterAdvice().execute();
                }
                return objec;
            }
        });
    }
}
执行前时间:1590722850655
bin登录游戏
执行后时间:1590722850656
bin赢下了一局英雄联盟,获得了100金币

Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler()):这个方法是重新生成了一个对象,通过类加载器和该类所有的接口生成。当前生成的方法都是空的,具体逻辑都会由InvocationHandler来实现。InvocationHandler我采用了内部类的方式来实现,具体逻辑都是通过invoke来访问目标对象。其调用流程就是:mian-->DynamicProxy-->InvocationHandler-->IGamePlayer .

cglib 动态代理

class IGamePlayer{

    private String name;

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

    public IGamePlayer() {
    }

    public void login() {
        System.out.println(name+"登录游戏");
    }

    public void playLOL() {
        System.out.println(name+"赢下了一局英雄联盟,获得了100金币");
    }
}
class DynamicProxy implements MethodInterceptor {

    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){

        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(target.getClass());

        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //模拟事务
        System.out.println("事务开始了");
        method.invoke(target,objects);
        System.out.println("事务结束了");
        return null;
    }
}
public static void main(String[] args) throws Exception {

        IGamePlayer iGamePlayer = new IGamePlayer("bin");
        DynamicProxy dynamicProxy = new DynamicProxy(iGamePlayer);
        IGamePlayer proxy = (IGamePlayer) dynamicProxy.getProxyInstance();
        proxy.login();
        proxy.playLOL();



     }
事务开始了
bin登录游戏
事务结束了
事务开始了
bin赢下了一局英雄联盟,获得了100金币
事务结束了
Heap

如例子,我们定义了一个目标对象类,没有实现接口,通过cglib的Enhancer工具类指定父类和回调,创建代理类。实现MethodInterceptor,重写intercept,相当于jdk动态代理的invoke。

有一点需要额外注意,若目标类是final或者目标方法是static和final的,则不会被cglib方法拦截

动态代理是springaop的核心,又分为jdk代理和cglib代理,前者通过接口生成代理后者通过定义父类的子类来生成代理(类不能为final,方法不能为static和final)

代理模式总结:

代理模式分为静态代理和动态代理。最大的区别就是静态代理是自己写代理,而动态代理是通过运行时动态的生成代理类。动态代理是springaop的核心,又分为jdk代理和cglib代理,前者通过接口生成代理后者通过定义父类的子类来生成代理(类不能为final,方法不能为static和final)。
代理模式或许是大家接触的最多的模式,有了springaop和aspectj这样优秀的工具,我们拿来定义即可。在学习aop框架的时候,要先弄清一些专业名词,切面、切入点、通知、织入,理解这些名词,知道代理模式的原理,学起aop框架就会游刃有余了。

装饰者模式

public interface Coffee {
    /**
     * 打印当前咖啡里有什么
     */
    void printMaterial();
}
public class BitterCoffee implements Coffee {
    @Override
    public void printMaterial() {
        System.out.println("咖啡");
    }
}
public class CoffeeDecorator implements Coffee {
    /**
     * 持有一个咖啡对象
     */
    private final Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public void printMaterial() {
        System.out.println("糖");
        this.coffee.printMaterial();
    }
}

使用

@Test
public void addSugerIntoCoffee {
    Coffee coffee = new BitterCoffee(); // 点了一杯苦咖啡
    coffee = new SugarDecorator(coffee); // 给咖啡加了点糖
    coffee.printMaterial(); // 糖 咖啡
}

代理模式

public class CoffeeProxy implements Coffee {
    private final Coffee coffee;

    public CoffeeProxy() {
        this.coffee = new BitterCoffee();
    }

    @Override
    public void printMaterial() {
        System.out.println("糖");
        this.coffee.printMaterial();
    }
}

@Test
public void addSugerIntoCoffee {
    Coffee coffee = new CoffeeProxy();
    coffee.printMaterial(); // 糖 咖啡
}

代理模式和装饰者模式的区别

在上面的例子中,装饰器模式是使用的调用者从外部传入的被装饰对象(coffee),调用者只想要你把他给你的对象装饰(加强)一下。而代理模式使用的是代理对象在自己的构造方法里面new的一个被代理的对象不是调用者传入的。调用者不知道你找了其他人,他也不关心这些事,只要你把事情做对了即可。

装饰器模式关注于在一个对象上动态地添加方法,而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例;当使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰器的构造器。

参考:

https://www.cnblogs.com/yanggb/p/10952843.html

辅助视频:

https://www.bilibili.com/video/BV157411R7Me?p=


    interface suger{
        void get();
    }
    class SweetSuger implements suger{
        @Override
        public void get() {
            System.out.println(" 甜糖");
        }
    }
    class OrangeSuger implements suger{
        suger suger;
        OrangeSuger(suger suger){
            this.suger = suger;
        }
        @Override
        public void get() {
            suger.get();
            System.out.println("橘子味的");
        }
    }
    class AppleSuger implements suger{
        suger suger;
        AppleSuger(suger suger){
            this.suger = suger;
        }
        @Override
        public void get() {
            suger.get();
            System.out.println(" 苹果味的");
        }
    }



suger sweetSuger = new SweetSuger();
      suger      orangeSuger = new OrangeSuger(sweetSuger);
      suger suger2 = new AppleSuger(orangeSuger);



 甜糖
橘子味的
 苹果味的

猜你喜欢

转载自blog.csdn.net/dandanforgetlove/article/details/106175089