栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式开局23种

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式开局23种

 设计模式

        设计模式是一种抽象的编程思想,它不会局限于某一种编程语言,也就是说在任何面向对象的编程语言中都有它的应用场景,在面向过程,函数式编程提起设计模式是没有任何意义的。

        设计模式中的六大原则:单一职责原则,里氏替换原则,依赖倒置原则,接口隔离原则,迪米特法则,开闭原则。

总体来说设计模式可以分为三大类:

        创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。

        结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。

        行为型模式(11种):策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。 

创建型模式
后续补发。。。。

结构型模式

代理模式Proxy:

        代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。为其他对象提供一种代理以控制对这个对象的访问。

Jdk动态代理实现:

        在java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接口、另一个则是 Proxy类,这个类和接口是实现我们动态代理所必须用到的。然后通过Proxy类产生的代理对象调用被代理对象的操作,而这个操作又被分发给InvocationHandler接口的 invoke方法具体执行。

  InvocationHandler:接口是给动态代理类实现的,负责处理被代理对象的操作的。

  Proxy:是用来创建动态代理类实例对象的,因为只有得到了这个对象我们才能调用那些需要代理的方法。

接下来我们看下实例,动老师在线开车动态指定代理时间是如何实现的:

package com.zking.hujianze.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;

interface ITeacherDao {
        String teach();
        ITeacherDao sleep(int minutes);
}
    
    class TeacherDao implements ITeacherDao{
        @Override
        public String teach() {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            return sdf.format(new Date())+":老师在线开车"; 
        }
    
        @Override
        public ITeacherDao sleep(int minutes) {
            System.out.println("老师开了" + minutes + "分钟");
            return this; 
        }
    }
    
    //真实代理类的外衣
    class TeacherDaoProxy{
        private ITeacherDao target;
        public TeacherDaoProxy(ITeacherDao target) {
            this.target = target;
        }
    
        public Object xxx(){
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            Object obj = null;
                            String methodName = method.getName();
                            System.out.println("目标方法" + methodName + ":jdk代理开始...");
                            System.out.println("真实代理对象:"+proxy.getClass());
                            System.out.println("目标对象:"+target.getClass());
                            if("sleep".equals(methodName)){
                            //method.invoke(target, args);
                            //obj = proxy;
                                obj = method.invoke(target, args);
                            }else {
                            //proxy是真实代理类,method是目标方法,args是目标方法携带的参数
                                obj = method.invoke(target, args);
                            }
                            System.out.println("目标方法" + methodName + ":jdk代理结束...");
                            return obj;
                        }
                    });
        }
    }

    public class Client {
        public static void main(String[] args) {
            TeacherDaoProxy proxy = new TeacherDaoProxy(new TeacherDao());
            ITeacherDao ins = (ITeacherDao) proxy.xxx();
            System.out.println("===========代理类实例被使用   begin=============");
            System.out.println(ins);
            System.out.println("===========代理类实例被使用   end=============");
            System.out.println(ins.teach());
            //System.out.println(proxy.execute());
            System.out.println("===========代理类实例被使用   begin=============");
            ins.sleep(10);
            System.out.println("===========代理类实例被使用   end=============");
            ins.sleep(20).sleep(60);
        }
    }

以下输出为:

===========代理类实例被使用   begin=============
目标方法toString:jdk代理开始...
真实代理对象:class com.zking.hujianze.proxy.$Proxy0
目标对象:class com.zking.hujianze.proxy.TeacherDao
目标方法toString:jdk代理结束...
com.zking.hujianze.proxy.TeacherDao@12a3a380
===========代理类实例被使用   end=============
目标方法teach:jdk代理开始...
真实代理对象:class com.zking.hujianze.proxy.$Proxy0
目标对象:class com.zking.hujianze.proxy.TeacherDao
目标方法teach:jdk代理结束...
2022-04-20:老师在线开车
===========代理类实例被使用   begin=============
目标方法sleep:jdk代理开始...
真实代理对象:class com.zking.hujianze.proxy.$Proxy0
目标对象:class com.zking.hujianze.proxy.TeacherDao
老师开了10分钟
目标方法sleep:jdk代理结束...
===========代理类实例被使用   end=============
目标方法sleep:jdk代理开始...
真实代理对象:class com.zking.hujianze.proxy.$Proxy0
目标对象:class com.zking.hujianze.proxy.TeacherDao
老师开了20分钟
目标方法sleep:jdk代理结束...
老师开了60分钟

cgLib的动态代理实现 :

package com.zking.hujianze.proxy.demo2;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

//import java.lang.reflect.InvocationHandler;//Cglib代理不被引用
import java.lang.reflect.Method;
//import java.lang.reflect.Proxy;//Cglib代理不被引用
import java.text.SimpleDateFormat;
import java.util.Date;

class TeacherDao {
    public String teach() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(new Date()) + ":老师在线开车";
    }
 
    public TeacherDao sleep(int minutes) {
        System.out.println("老师开了" + minutes + "分钟");
        return this;
    }
 
}
 
//真实代理类的外衣
class TeacherDaoProxy implements MethodInterceptor {
    private Object target;
 
    public TeacherDaoProxy(Object target) {
        this.target = target;
    }
 
    //返回一个代理对象:	是 target  对象的代理对象
    public Object getProxyInstance() {
        //1. 创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2. 设置父类
        enhancer.setSuperclass(target.getClass());
        //3. 设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }
 
    
    @Override
    public Object intercept(Object proxyIns, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        String methodName = method.getName();
        Object res;
        System.out.println("目标方法" + methodName + ":cglib代理开始...");
        System.out.println("真实代理对象:" + proxyIns.getClass());
        System.out.println("目标对象:" + target.getClass());
        if ("sleep".equals(methodName)) {
            //method.invoke(target, args);
            //obj = proxy;
            res = method.invoke(target, args);
            //res = methodProxy.invokeSuper(proxyIns,args);
            res = proxyIns;
        } else {
            //proxy是真实代理类,method是目标方法,args是目标方法携带的参数
            res = method.invoke(target, args);
        }
        System.out.println("目标方法" + methodName + ":cglib代理结束...");
        return res;
    }
}
 
public class Client {
    public static void main(String[] args) {
        TeacherDao proxy = (TeacherDao) new TeacherDaoProxy(new TeacherDao()).getProxyInstance();
        proxy.sleep(111).sleep(222);
    }
}

 以下输出为:

目标方法sleep:cglib代理开始...
真实代理对象:class com.zking.hujianze.proxy.demo2.TeacherDao$$EnhancerByCGLIB$$ebe7c940
目标对象:class com.zking.hujianze.proxy.demo2.TeacherDao
老师开了111分钟
目标方法sleep:cglib代理结束...
目标方法sleep:cglib代理开始...
真实代理对象:class com.zking.hujianze.proxy.demo2.TeacherDao$$EnhancerByCGLIB$$ebe7c940
目标对象:class com.zking.hujianze.proxy.demo2.TeacherDao
老师开了222分钟
目标方法sleep:cglib代理结束...

Cglib和jdk动态代理的区别:

        1,Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理

        2,Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理

装饰者模式Decorator:

        指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。

结构:

        抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。
        具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责。
        抽象装饰角色:继承或实现抽象构件,并包含具体构件的实例,可以通过子类扩展具体构件的功能。
        具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

示例:单体咖啡与调味组合的单体饮料计价

        Component:组件(主体)

        ConcreteComponent:被装饰者 

        Decorator:装饰者

注意:ConcreteComponent、Decorator都会实现或继承Component

package com.zking.hujianze.decorator;

public abstract class Drink {
    protected double price;
    protected int n;
    protected DrinkSeasoning seasoning;
    public abstract double getPrice();
}

abstract class Coffee extends Drink { }

abstract class Juice extends Drink { }

class ChinaCoffee extends Coffee{
    ChinaCoffee(double price,int n){ this.price = price;this.n = n; }

    @Override
    public double getPrice() { return this.price*this.n+this.seasoning.getPrice(); }
}

package com.zking.hujianze.decorator;

public interface DrinkSeasoning { public abstract double getPrice();}

class ADrinkSeasoning implements DrinkSeasoning{
    protected double price;
    protected int n;

    ADrinkSeasoning(double price,int n){ this.price = price;this.n = n; }

    @Override
    public double getPrice() { return this.price*this.n; }
}


class BDrinkSeasoning implements  DrinkSeasoning{
    private double price;
    protected int n;
    BDrinkSeasoning(double price,int n){ this.price = price;this.n = n; }
    @Override
    public double getPrice() { return this.price*this.n; }
}

 以下输出为:

中式咖啡1份+A调料2份,最终价格为:10.0
package com.zking.hujianze.decorator;
public class Client {
    public static void main(String[] args) {
        ChinaCoffee chinaCoffee = new ChinaCoffee(6, 1);
        ADrinkSeasoning aDrinkSeasoning = new ADrinkSeasoning(2, 2);
        chinaCoffee.seasoning = aDrinkSeasoning;
        System.out.println("中式咖啡1份+A调料2份,最终价格为:" + chinaCoffee.getPrice());

    }
}

 问题1:如果下单中式咖啡1份+A调料3份+B调料2份,计算出最终的价格,那代码该怎么改动呢?
 问题2:在原有的咖啡订单下,追加B调料2份,计算出最终的价格,那代码该怎么改动呢?

使用装饰模式进行设计:

package com.zking.hujianze.decorator.demo2;

public abstract class Drink {
    protected double price;
    protected int n;

    public abstract double getPrice();
}

abstract class Coffee extends Drink { }

abstract class Juice extends Drink { }

class ChinaCoffee extends Coffee {
    ChinaCoffee(double price, int n) { this.price = price;this.n = n; }

    @Override
    public double getPrice() {
        return this.price * this.n;
    }
}

package com.zking.hujianze.decorator.demo2;

public class DecoratorDrink extends Drink {
    private Drink drink;

    public DecoratorDrink(Drink drink, double price, int n) {
        this.drink = drink;
        this.price = price;
        this.n = n;
    }

    @Override
    public double getPrice() {
        return this.price * this.n + drink.getPrice();
    }
}

class ADecoratorDrink extends DecoratorDrink {
    public ADecoratorDrink(Drink drink, double price, int n) {
        super(drink, price, n);
    }
}

class BDecoratorDrink extends DecoratorDrink {
    public BDecoratorDrink(Drink drink, double price, int n) {
        super(drink, price, n);
    }
}

package com.zking.hujianze.decorator.demo2;
public class Client {
    public static void main(String[] args) {
        ChinaCoffee chinaCoffee = new ChinaCoffee(10,1);
        //假定A类调料2元一份,B类调料3元一份
        Drink order = new ADecoratorDrink(chinaCoffee, 2, 2);
        System.out.println("中式咖啡1份+A调料2份,最终价格为:"+order.getPrice());

        //问题1:如果我要下单中式咖啡1份+A调料3份+B调料2份,计算出最终的价格,那代码该怎么改动呢?
        order = new ADecoratorDrink(order,2,1);
        System.out.println("中式咖啡1份+A调料3份,最终价格为:"+order.getPrice());
        order = new BDecoratorDrink(order,3,2);
        System.out.println("中式咖啡1份+A调料3份+B调料2份,最终价格为:"+order.getPrice());

        //问题2:在原有的咖啡订单下,追加B调料2份,计算出最终的价格,那代码该怎么改动呢?
        order = new BDecoratorDrink(order,3,2);
        System.out.println("中式咖啡1份+A调料3份+B调料4份,最终价格为:"+order.getPrice());
    }
}

 以下输出为:

中式咖啡1份+A调料2份,最终价格为:14.0
中式咖啡1份+A调料3份,最终价格为:16.0
中式咖啡1份+A调料3份+B调料2份,最终价格为:22.0
中式咖啡1份+A调料3份+B调料4份,最终价格为:28.0

要点:

        1.装饰者对象和被装饰者对象有相同的超类型。

        2.可以用一个或多个装饰者包装一个对象。

        3.装饰者可以在被装饰者行为之前或之后加上自己的行为,以达到特定的目的。

        4.对象可以在任何时候被装饰。可以在运行时动态的、不限量的用装饰者来装饰对象。

        5.装饰者利用继承来达到“类型匹配”,而不是利用继承“获得行为”。装饰者能够取代被装饰者。

        6.将装饰者与组件组合时,就是在加入新的行为。新的行为并不是通过继承得来,而是通过组合对象得来的。

行为型模式

后续补发。。。。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820888.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号