面试 --- java 设计模式

** 简述 设计模式 七大原则 **

1.开发封闭原则 : 对扩展开放  ,  对修改封闭。  
	 		在程序需要就行扩展的时候 , 不能去修改 原有的代码, 形成一个 热插拔 的效果。

2.单一职责原则:  一个类 接口 或 方法  只负责  一个 职责  ,降低代码复杂度  以及 
								变更引起的风险。

3.依赖倒置原则: 针对接口编程 , 依赖于 抽象类 或 接口 	而不依赖于  具体实现类。

4.接口隔离原则: 将不同 功能 定义在不同接口中 实现 接口隔离。

5.里氏替换原则: 任何 基类 可以出现的 地方  ,子类 都一定可以 出现。

6.迪米特原则: 每个模块 都要 对 其他模块 尽可能 少地 了解 或 依赖 ,降低 代码耦合度。

7.合成复用原则: 尽量 使用  组合/聚合 而不是  继承  达到 软件复用 的 目的。

** 简述 设计模式 的 分类 **

1.创建型模式: 在创建对象的 同时 隐藏 逻辑 ,不使用 new 直接 实例化对象

	有(工厂方法模式  抽象工厂模式  单例模式   建造者模式   原型模式)

2.结构型模式: 通过 类和接口 间的 继承和引用 实现 创建 复杂结构的对象。
有 (适配器模式 装饰器模式 代理模式 外观模式 桥接模式 组合模式 享元模式)

3.行为型模式: 通过 类之间 不同 的 通信方法 实现 不同行为。
有 (策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式)

** 什么 是 策略 模型 ? **
策略模型 定义了 算法族, 分别封装起来,让他们之间 可以相互 替换 ,
此模式让 算法的 变化 独立 于 使用 算法的客户。

优点 : 遵循了 开闭原则 ,扩展性好。

缺点 : 随着 策略的 增加, 对外暴露越来越多。

策略模式

例子:
出行方式如 开车,坐火车,坐飞机,可以把出行方式作为策略封装起来,可以在不改动原有的类的基础上,新增新的交通工具

使用 Compartor接口实现比较器策略,可以随意使用 任意条件进行比较排序。
如: 猫的 高度,重量。
只需要实现 Compartor接口,实现接口中的方法。
可以在不修改原有代码的基础上,对原有功能的一个扩展,符合开闭原则。

具体代码实现:
public static void main(String[] args) {
Cat[] cats={new Cat(1,1),new Cat(21,0),new Cat(3,3)};
SortCat s=new SortCat();
s.sort(cats,new CatCom());
System.out.println(Arrays.toString(cats));
}

public class Cat {
int he;
int we;

public Cat(int he, int we) {
    this.he = he;
    this.we = we;
}

@Override
public String toString() {
    return "Cat{" +
            "he=" + he +
            ", we=" + we +
            '}';
}

}

public class CatCom implements Comparator {
public int compare(Cat o1, Cat o2) {
if (o1.he>o2.he)
return -1;
else if (o1.he < o2.he)
return 1;
else return 0;
}
}

public class SortCat {
public void sort(T[] t, Comparator comparator) {
for (int i = 0; i < t.length; i++) {
int min = i;
for (int j = 0; j < t.length; j++) {
min = comparator.compare(t[j], t[min]) == -1 ? j : min;
}
swap(t, i, min);
}
}

public void swap(T[] arr, int i, int j) {
    T t = arr[i];
    arr[i] = arr[j];
    arr[j] = t;
}

以生活中的例子来说,比如我们要出去旅游,选择性很多,可以选择骑车、开车、坐飞机、坐火车等,就可以使用策略模式,把每种出行作为一种策略封装起来,后面增加了新的交通方式了,如超级高铁、火箭等,就可以不需要改动原有的类,新增交通方式即可,这样也符合软件开发的开闭原则。 策略模式实现代码如下:

/\* \* 声明旅行 \*/
interface ITrip {
    void going();
}
class Bike implements ITrip {
    @Override
    public void going() {
        System.out.println("骑自行车");
    }
}
class Drive implements ITrip {
    @Override
    public void going() {
        System.out.println("开车");
    }
}



/\* \* 定义出行类 \*/
class Trip {
    private ITrip trip;

    public Trip(ITrip trip) {
        this.trip = trip;
    }

    public void doTrip() {
        this.trip.going();
    }
}
/\* \* 执行方法 \*/
public class StrategyTest {
    public static void main(String[] args) {
        Trip trip = new Trip(new Bike());
        trip.doTrip();
    }
}

在这里插入图片描述

public  abstract  class Duck {
    //接口
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public abstract void display();

    public void swim()
    {
        System.out.println("all duck float,evendecoys");
    }

    public void performFly(){
        flyBehavior.fly();
    }

    public void performQucak(){
        quackBehavior.quack();
    }

    public FlyBehavior getFlyBehavior() {
        return flyBehavior;
    }

    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }

    public QuackBehavior getQuackBehavior() {
        return quackBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
}




public class MallardDuck extends Duck{
    @Override
    public void display() {
        System.out.println("i am real Mallard duck");
    }

    public MallardDuck() {
        flyBehavior=new FlyWithWings();
        quackBehavior=new Qucak();
    }
}


public class ModeDuck extends Duck{
    @Override
    public void display() {
        System.out.println("i am Model duck");
    }

    public ModeDuck() {
        flyBehavior=new FylNoWay();
        quackBehavior=new Qucak();
    }
}

public interface FlyBehavior {

    public void fly();
}

public class FlyRockPowered implements  FlyBehavior{
    @Override
    public void fly() {
        System.out.println("iam flying with a rocket");
    }
}

public class FlyWithWings implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("I can fly");
    }
}


public class FylNoWay implements FlyBehavior{
    @Override
    public void fly() {
        System.out.println("i am can not  fly");
    }
}


public interface QuackBehavior {
    public void quack();
}

public class Qucak implements QuackBehavior{
    @Override
    public void quack() {
        System.out.println("Qucak");
    }
}


public class MinDuckSimulator {

    public static void main(String[] args) {
        Duck duck=new MallardDuck();
        duck.performQucak();
        duck.performFly();

        duck.swim();
        duck.display();

        Duck model=new ModeDuck();
        model.performFly();
        model.setFlyBehavior(new FlyRockPowered());
        model.performFly();
    }
}


在这里插入图片描述


**单例模式 **

public class Singletion {
//双层检查加锁
    //volatile 确保 uniqueInstance 变量被初始化 成  Singletion实例时候,
    多个线程能正确处理 uniqueInstance 变量
    private volatile static Singletion uniqueInstance;
    
    private Singletion(){};
 
    public  static  Singletion getInstance(){
        //检查实例  如果不存在就进入同步框块
        if(uniqueInstance == null){
            //只有第一次才彻底执行这里
            synchronized(Singletion.class){
                 //进入区块后,再检查一次,如果还是null,才创建实例
                if(uniqueInstance ==null){
                    //进入区块后,再检查一次,如果还是null,才创建实例
                    uniqueInstance=new Singletion();
                }
            }
        }
        return  uniqueInstance;
    }

}

单例模式 确保程序中 一个类 最多只有一个实例。
单例模式 也提供 访问 这个实例的 全局点。
在java 中 实现单例模式 需要私有构造器 ,一个静态方法和静态变量
确定性能和资源上的限制 ,然后小心选择适当的 方式 实现 单例模式,以解决多线程问题。

在这里插入图片描述
** 实现一:立即加载 / “饿汉模式” **

立即加载就是使用类的时候已经将对象创建完毕(不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故又被称为“饿汉模式”),常见的实现办法就是直接new实例化。

	public class Singleton {

		    // 将自身实例化对象设置为一个属性,并用static、final修饰
		    private static final Singleton instance = new Singleton();
		    
		    // 构造方法私有化
		    private Singleton() {}
		    
		    // 静态方法返回该实例
		    public static Singleton getInstance() {
		        return instance;
		    }
}

饿汉模式”的优缺点:

优点:实现起来简单,没有多线程同步问题。

缺点:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。


** 实现二:延迟加载 / “懒汉模式” **

延迟加载就是调用get()方法时实例才被创建(先不急着实例化出对象,等要用的时候才给你创建出来。不着急,故又称为“懒汉模式”),常见的实现方法就是在get方法中进行new实例化。

public class Singleton {

		    // 将自身实例化对象设置为一个属性,并用static修饰
		    private static Singleton instance;
		    
		    // 构造方法私有化
		    private Singleton() {}
		    
		    // 静态方法返回该实例
		    public static Singleton getInstance() {
		        if(instance == null) {
		            instance = new Singleton();
		        }
		        return instance;
		    }
}

“懒汉模式”的优缺点:

优点:实现起来比较简单,当类SingletonTest被加载的时候,静态变量static的instance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,因此在某些特定条件下会节约了内存。

缺点:在多线程环境中,这种实现方法是完全错误的,根本不能保证单例的状态。


** 实现三:线程安全的“懒汉模式” **

public class Singleton {

    // 将自身实例化对象设置为一个属性,并用static修饰
    private static Singleton instance;
    
    // 构造方法私有化
    private Singleton() {}
    
		    // 静态方法返回该实例,加synchronized关键字实现同步
		    public static synchronized Singleton getInstance() {
		        if(instance == null) {
		            instance = new Singleton();
		        }
		        return instance;
		    }
}

在这里插入图片描述

优点:在多线程情形下,保证了“懒汉模式”的线程安全。

缺点:众所周知在多线程情形下,synchronized方法通常效率低,显然这不是最佳的实现方案。


** 代理模式**

代理模式— 为另一个对象 提供 一个 替身 或 占位符 以 访问 这个对象。

使用代理模式 创建 代表 ,让 代表对象 控制 某对象的访问, 被代理对象
可以是 远程的对象 ,创建 开销大 的 对象 或 需要安全控制的对象。


静态代理 :要求被代理类和代理类同时实现相应的一套接口,通过代理类调用重写接口的方法,实际上调用的是原始对象的同样的方法。

*静态代理实现步骤:

  • 定义一个接口及其实现类;
  • 创建一个代理类同样实现这个接口
  • 将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。
1.定义发送短信的接口
package Poxy.jintai;

public interface SsmService {
    String send(String name);
}

2.实现发送短信的接口
package Poxy.jintai;

public class SsmServiceImpl implements SsmService{
    @Override
    public String send(String message) {
        System.out.println("send message: "+message);
        return message;
    }
}


3.创建代理类并同样实现发送短信的接口
package Poxy.jintai;

public class SsmPoxy {
    private final SsmService ssmService;


    public SsmPoxy(SsmService ssmService) {
        this.ssmService = ssmService;
    }

    public String send(String message){
        //调用方法之前,我们可以添加自己的操作
        System.out.println("before method send()");
        ssmService.send(message);
        //调用方法之后,我们同样可以添加自己的操作
        System.out.println("after method send()");
        return null;
    }

}


4.实际使用
package Poxy.jintai;

public class PoxyMain {
    public static void main(String[] args) {
        SsmService ssmService=new SsmServiceImpl();
        SsmPoxy ssmPoxy=new SsmPoxy(ssmService);
        ssmPoxy.send("java");
    }
}


5.运行上述代码之后,控制台打印出:
before method send()
send message: java
after method send()

总结:
可以输出结果看出,我们已经增加了 SmsServiceImpl 的send()方法。


动态代理 : 在运行时 动态地 创建 一个代理类 , 实现一个或 多个 接口,并将 方法的 调用 转发到 你 指定的类

从 JVM 角度来说,动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。

在 Java 动态代理机制中 InvocationHandler 接口和 Proxy 类是核心

Proxy 类中使用频率最高的方法是:newProxyInstance() ,这个方法主要用来生成一个代理对象。

public static Object newProxyInstance
(ClassLoader loader,
 Class<?>[] interfaces,
 InvocationHandler h)
        throws IllegalArgumentException
    {
        ......
    }

loader :类加载器,用于加载代理对象。
interfaces : 被代理类实现的一些接口;
h : 实现了 InvocationHandler 接口的对象;

要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。
当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。

public interface InvocationHandler {

 /**
   * 当你使用代理对象调用方法的时候实际会调用到这个方法
   */
public Object invoke
(Object proxy, Method method, Object[] args)
        throws Throwable;
}

proxy :动态生成的代理类
method : 与代理类对象调用的方法相对应
args : 当前 method 方法的参数

通过Proxy 类的 newProxyInstance() 创建的代理对象在调用方法的时候,实际会调用到实现InvocationHandler 接口的类的 invoke()方法。

可以在 invoke() 方法中自定义处理逻辑,比如在方法执行前后做什么事情。

*JDK 动态代理类使用步骤

  • 定义一个接口及其实现类
  • 自定义 InvocationHandler 并重写invoke方法,在 invoke 方法中我们会调用原生方法(被代理类的方法)并自定义一些处理逻辑
  • 通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象
定义发送短信的接口
package Poxy.dongtai;

public interface SsmService {
    String send(String name);
}

实现发送短信的接口
package Poxy.dongtai;

public class SsmServiceImpl implements SsmService {
    @Override
    public String send(String message) {
        System.out.println("send message: "+message);
        return message;
    }
}

定义一个 JDK 动态代理类
package Poxy.dongtai;

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

/**
 * JDK 动态代理类
 */
public class DebugInvocationHandler implements InvocationHandler {

    /**
     * 代理类中的真实对象
     */
    private final Object target;

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


    public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        //调用方法之前,我们可以添加自己的操作
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);
        //调用方法之后,我们同样可以添加自己的操作
        System.out.println("after method " + method.getName());
        return result;
    }
}

获取代理对象的工厂类
package Poxy.dongtai;

import java.lang.reflect.Proxy;

/**
 * 获取代理对象的工厂类
 */
public class JdkProxyFactory {
    public static Object getProxy(Object target){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(), //目标类 的 类加载
                target.getClass().getInterfaces(),  //代理需要 实现的接口 可指定多个
                new DebugInvocationHandler(target)  // 代理对象 对应的自定义  InvocationHandler
        );
    }
}

实际使用
package Poxy.dongtai;

public class DongTaiMain {
    public static void main(String[] args) {
        SsmService ssmService= (SsmService) JdkProxyFactory.getProxy(new SsmServiceImpl());
        ssmService.send("java");
    }
}

运行上述代码之后,控制台打印出:
before method send
send message: java
after method send

JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类


*CGLIB 动态代理机制
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB 通过继承方式实现代理。很多知名的开源框架都使用到了CGLIB, 例如 Spring 中的 AOP 模块中:如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。

在 CGLIB 动态代理机制中 MethodInterceptor 接口和 Enhancer 类是核心。

你需要自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法。

public interface MethodInterceptor
extends Callback{
    // 拦截被代理类中的方法
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
                               MethodProxy proxy) throws Throwable;
}
obj :被代理的对象(需要增强的对象)
method :被拦截的方法(需要增强的方法)
args :方法入参
proxy :用于调用原始方法

可以通过 Enhancer类来动态获取被代理类,当代理类调用方法的时候,实际调用的是 MethodInterceptor 中的 intercept 方法

*CGLIB 动态代理类使用步骤

  • 定义一个类
  • 自定义 MethodInterceptor 并重写 intercept 方法,intercept 用于拦截增强被代理类的方法,和 JDK 动态代理中的 invoke 方法类似
  • 通过 Enhancer 类的 create()创建代理类

不同于 JDK 动态代理不需要额外的依赖。CGLIB(Code Generation Library) 实际是属于一个开源项目,如果你要使用它的话,需要手动添加相关依赖

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.3.0</version>
</dependency>
实现一个使用阿里云发送短信的类
package github.javaguide.dynamicProxy.cglibDynamicProxy;

public class AliSmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

自定义 MethodInterceptor(方法拦截器)
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 自定义MethodInterceptor
 */
public class DebugMethodInterceptor implements MethodInterceptor {


    /**
     * @param o           代理对象(增强的对象)
     * @param method      被拦截的方法(需要增强的方法)
     * @param args        方法入参
     * @param methodProxy 用于调用原始方法
     */
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //调用方法之前,我们可以添加自己的操作
        System.out.println("before method " + method.getName());
        Object object = methodProxy.invokeSuper(o, args);
        //调用方法之后,我们同样可以添加自己的操作
        System.out.println("after method " + method.getName());
        return object;
    }

}

获取代理类
import net.sf.cglib.proxy.Enhancer;

public class CglibProxyFactory {

    public static Object getProxy(Class<?> clazz) {
        // 创建动态代理增强类
        Enhancer enhancer = new Enhancer();
        // 设置类加载器
        enhancer.setClassLoader(clazz.getClassLoader());
        // 设置被代理类
        enhancer.setSuperclass(clazz);
        // 设置方法拦截器
        enhancer.setCallback(new DebugMethodInterceptor());
        // 创建代理类
        return enhancer.create();
    }
}

实际使用
AliSmsService aliSmsService = (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
aliSmsService.send("java");
运行上述代码之后,控制台打印出:
before method send
send message:java
after method send


*JDK 动态代理和 CGLIB 动态代理对比

JDK 动态代理只能代理实现了接口的类或者直接代理接口,
而 CGLIB 可以代理未实现任何接口的类。

CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用,因此不能代理声明为 final 类型的类和方法。

就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。


*静态代理和动态代理的对比

灵活性 :动态代理更加灵活,不需要必须实现接口,可以直接代理实现类,并且可以不需要针对每个目标类都创建一个代理类。另外,静态代理中,接口一旦新增加方法,目标对象和代理对象都要进行修改,这是非常麻烦的!

JVM 层面 :静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。而动态代理是在运行时动态生成类字节码,并加载到 JVM 中的。


保护代理:这是一种根据访问权限 决定 客户可否 访问对象的代理。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


观察者模式

出版者+订阅者 = 观察者模式

观察者模式:

定义了 对象之间的 一对多依赖, 这样一来,当一个对象改变状态时,它的 所有依赖者 都会 收到 通知 并 自动更新

观察者模式 定义了 一系列 对象之间 的 一对多关系

当一个对象改变状态, 其他依赖者 都会收到 通知

松耦合
当两个对象之间松耦合, 它们依然可以 交互 , 但是不太清楚彼此的细节

观察者模式提供了 一种 设计对象, 让 主题和观察者 之间 松耦合

主题(可观察者)用一个 共同的接口 来更新观察者

使用观察者模式 可以从 被观察者 推(push) 或者 拉(pull) 数据

有多个观察者时, 不可以 依赖特定的通知次序

SWing 使用了大量 观察者模式,
在这里插入图片描述

package guangchazhe;
//主题接口
public interface Subject {

    //这两个方法都需要一个 观察者作为变量 该观察者用于 注册和删除
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);

    //当主题状态改变时候,用于通知所有观察者
    public void notifyObservers();

    //所有观察者都需要 实现 update()方法, 以实现 观察者接口
    public interface Observer
    {
        //当气象观测值改变时, 主题会把这些状态值当做方法的参数 传递给观察者
        public void  update(float temp,float humidity,float perssure);
    }

    //当布告栏需要显示的时候 调用此方法
    public  interface DisplayElement{
        public void display();
    }
}

package guangchazhe;



//布告栏
public class CurrentConditionsDisplay implements Subject.Observer, Subject.DisplayElement {
    private float temperature;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    public void update(float temp, float humidity, float perssure) {
        this.temperature=temp;
        this.humidity=humidity;
        display();
    }

    @Override
    public void display() {
        float t = temperature;
        float rh = humidity;
       float heatIndex = (float)
                (
                        (16.923 + (0.185212 * t)) +
                                (5.37941 * rh) -
                                (0.100254 * t * rh) +
                                (0.00941695 * (t * t)) +
                                (0.00728898 * (rh * rh)) +
                                (0.000345372 * (t * t * rh)) -
                                (0.000814971 * (t * rh * rh)) +
                                (0.0000102102 * (t * t * rh * rh)) -
                                (0.000038646 * (t * t * t)) +
                                (0.0000291583 * (rh * rh * rh)) +
                                (0.00000142721 * (t * t * t * rh)) +
                                (0.000000197483 * (t * rh * rh * rh)) -
                                (0.0000000218429 * (t * t * t * rh * rh)) +
                                (0.000000000843296 * (t * t * rh * rh * rh)) -
                                (0.0000000000481975 * (t * t * t * rh * rh * rh)));

        System.out.println(temperature +":"+
                            humidity+":");
        System.out.println(heatIndex);
    }
}

package guangchazhe;


import java.util.ArrayList;

//在这个类中 实现主题接口
public class WeatherData implements Subject {

    private ArrayList obsevers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){
        obsevers=new ArrayList();
    }

    //注册
    public void registerObserver(Observer o) {
        obsevers.add(o);
    }

    //取消注册
    public void removeObserver(Observer o) {
        final int i = obsevers.indexOf(o);
        if (i >=0){
            obsevers.remove(i);
        }
    }

    //通知
    public void notifyObservers() {
        //把状态通知到了所有的订阅者
        for (int i = 0; i < obsevers.size(); i++) {
            Observer observer= (Observer) obsevers.get(i);
            observer.update(temperature,humidity,pressure);
        }
    }
    //当获取到最新值通知 观察者
    public void measuresChange(){
        notifyObservers();
    }
    public void setMeasures(float temperature,float humidity,float pressure)
    {
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measuresChange();
    }

    public static void main(String[] args) {
        WeatherData weatherData=new WeatherData();
        CurrentConditionsDisplay conditionsDisplay=new CurrentConditionsDisplay(weatherData);

        weatherData.setMeasures(60,65,30.4f);
        weatherData.setMeasures(160,165,130.4f);
        weatherData.setMeasures(260,265,130.4f);
    }
}

java自带API

package guangchazhe.api;

import guangchazhe.Subject;

import java.util.Observable;
import java.util.Observer;

//布告栏
public class CurrentConditionsDisplay implements Observer, Subject.DisplayElement {
    private float temperature;
    private float humidity;
    private Observable observable;


    public CurrentConditionsDisplay(Observable observable) {
        this.observable = observable;
        //注册
        observable.addObserver(this);
    }
    @Override
    public void update(Observable o, Object arg) {
    if (o instanceof  WeatherData){
        WeatherData weatherData= (WeatherData) o;
        this.temperature=weatherData.getTemperature();
        this.humidity=weatherData.getHumidity();
        display();
        }
    }
    @Override
    public void display() {
        float t = temperature;
        float rh = humidity;
       float heatIndex = (float)
                (
                        (16.923 + (0.185212 * t)) +
                                (5.37941 * rh) -
                                (0.100254 * t * rh) +
                                (0.00941695 * (t * t)) +
                                (0.00728898 * (rh * rh)) +
                                (0.000345372 * (t * t * rh)) -
                                (0.000814971 * (t * rh * rh)) +
                                (0.0000102102 * (t * t * rh * rh)) -
                                (0.000038646 * (t * t * t)) +
                                (0.0000291583 * (rh * rh * rh)) +
                                (0.00000142721 * (t * t * t * rh)) +
                                (0.000000197483 * (t * rh * rh * rh)) -
                                (0.0000000218429 * (t * t * t * rh * rh)) +
                                (0.000000000843296 * (t * t * rh * rh * rh)) -
                                (0.0000000000481975 * (t * t * t * rh * rh * rh)));

        System.out.println("javaAPI");
        System.out.println(temperature +":"+
                            humidity+":");
        System.out.println(heatIndex);
    }


}



package guangchazhe.api;



import java.util.Observable;

//在这个类中 实现主题接口
public class WeatherData extends Observable {

    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData(){

    }

    //当获取到最新值通知 观察者
    public void measuresChange(){
        //指示状态已经改变
        setChanged();
        notifyObservers();
    }
    public void setMeasures(float temperature,float humidity,float pressure)
    {
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measuresChange();
    }

    public float getTemperature() {
        return temperature;
    }
    public float getHumidity() {
        return humidity;
    }
    public float getPressure() {
        return pressure;
    }



    public static void main(String[] args) {
        WeatherData weatherData=new WeatherData();
        CurrentConditionsDisplay conditionsDisplay=new CurrentConditionsDisplay(weatherData);

       // weatherData.deleteObserver(conditionsDisplay);
        weatherData.setMeasures(60,65,30.4f);
        weatherData.setMeasures(160,165,130.4f);
        weatherData.setMeasures(260,265,130.4f);


    }
}


**装饰者模式 **

含义: 动态地 将 责任 附加到 对象上, 想要 扩展 功能 ,装饰者 提供 有别于 继承的 另一种选择,
要点:
在这里插入图片描述

示例 :
实现 装饰者模式中 -咖啡

package 装饰者模式.Coffe;

/**
 * date 2021/11/721:42
 *
 * @author mzr
 * @target :实现 装饰者模式中  -咖啡
 **/
// Beverage 是一个 抽象类 ,有 两个方法 getDescip() 和 cost()
public abstract class Beverage {
    String desciption="Unknow Beverage";
    public String getDesciption(){
        return desciption;
    }
    public abstract double cost();

    //装饰类
    public abstract static class CondimentDecorator extends Beverage{
        public abstract String getDesciption();
    }

    //饮料
    //Espresso
    public static class Espresso extends  Beverage{

        public Espresso(){
            desciption="Espresso";
        }
        public double cost() {
            return 1.99;
        }
    }

    //饮料
    //DaikRoast
    public static class DaikRoast extends Beverage{
        public DaikRoast(){
            desciption="DaikRoast";
        }

        public double cost() {
            return 0.89;
        }
    }

    //饮料
    //HouseBlend
    public class HouseBlend extends Beverage{
        public HouseBlend(){
            desciption="HouseBlend";
        }

        public double cost() {
            return 0.89;
        }
    }

    //调料
    public static class Mocha extends CondimentDecorator{

        Beverage beverage;
        public Mocha(Beverage beverage){
            this.beverage=beverage;
        }

        @Override
        public double cost() {
            return 0.20+beverage.cost();
        }

        @Override
        public String getDesciption() {
            return beverage.getDesciption()+" ,Mocha";
        }
    }

    //调料
    public static class Whip extends CondimentDecorator{

        Beverage beverage;
        public Whip(Beverage beverage){
            this.beverage=beverage;
        }

        @Override
        public double cost() {
            return 0.30+beverage.cost();
        }

        @Override
        public String getDesciption() {
            return beverage.getDesciption()+" ,Whip";
        }
    }

    //调料
    public static class Soy extends CondimentDecorator{

        Beverage beverage;
        public Soy(Beverage beverage){
            this.beverage=beverage;
        }

        @Override
        public double cost() {
            return 0.40+beverage.cost();
        }

        @Override
        public String getDesciption() {
            return beverage.getDesciption()+" ,Soy";
        }
    }
}

主方法

package 装饰者模式.Coffe;

/**
 * date 2021/11/721:56
 *
 * @author mzr
 * @target : 主方法
 **/
public class StarbuzzCoffe {


    public static void main(String[] args) {
        Beverage beverage=new Beverage.Espresso();
        System.out.println(beverage.getDesciption() +"$"+beverage.cost());

        Beverage beverage2=new Beverage.DaikRoast();
        beverage2=new Beverage.Mocha(beverage2);
        beverage2=new Beverage.Whip(beverage2);
        beverage2=new Beverage.Mocha(beverage2);
        System.out.println(beverage2.getDesciption() +"$"+beverage2.cost());

        Beverage beverage3=new Beverage.DaikRoast();
        beverage3=new Beverage.Mocha(beverage3);
        beverage3=new Beverage.Whip(beverage3);
        beverage3=new Beverage.Soy(beverage3);
        System.out.println(beverage3.getDesciption() +"$"+beverage3.cost());
    }
}
Espresso$1.99
DaikRoast ,Mocha ,Whip ,Mocha$1.59
DaikRoast ,Mocha ,Whip ,Soy$1.79

编写自己的 IO 装饰者

package 装饰者模式.IO;

import java.io.*;
import java.nio.charset.Charset;

/**
 * date 2021/11/722:05
 *
 * @author mzr
 * @target :编写自己的 IO 装饰者
 **/
public class LowerCaseInputStream extends FilterInputStream {

    protected LowerCaseInputStream(InputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c= super.read();
        return (c == -1 ? c : Character.toLowerCase(c));
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int reslut=super.read(b, off, len);
        for (int i = off; i <off+reslut ; i++) {
            b[i]= (byte) Character.toLowerCase(b[i]);
        }
        return reslut;
    }

    public static void main(String[] args) {
        int c;
        try {
                InputStream in = new LowerCaseInputStream(
                        new BufferedInputStream(
                                new FileInputStream("test.txt")));
                while ( (c = in.read()) >=0)
                {
                    System.out.println(c);
                }
            }
        catch (IOException e){
            e.printStackTrace();
        }
    }
}

工厂模式

抽象工厂模式 — 提供一个 接口 , 用于 创建 相关 或 依赖的 家族, 而不需要 明确 指定 具体类

工厂方法模式 — 定义了 一个 创建 对象的 接口 , 但由于 类 决定 要 实例化 是 哪一个 。

工厂 方法让 类 把 实例化 推迟 到 子类

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值