浅谈常用的设计模式

52 阅读19分钟

单例模式

观察者模式

装饰模式

一.单例模式

1.饿汉式

(1).静态常量方式

public class SingleTon {
    private SingleTon(){}
    private static final SingleTon instance=new SingleTon();
    public static  SingleTon getInstance(){
        return instance;
    }
}
 

(2).静态代码块

public class SingleTon {
    private SingleTon() {
    }
    private static SingleTon singleTon;
    static {
        singleTon=new SingleTon();
    }
    public static SingleTon getInstance(){
        return  singleTonSeven;
    }
}

优点:

  • 实现简单,
  • 线程安全,
  • 无锁获取实例的速度快

缺点:

  • 内存浪费(该类在加载的时候就会初始化该实例,不管是否使用,都会被加载到内存)

  • 无法延迟加载

  • 初始化时无法传递参数.

2.懒汉式

(1).线程不安全版本

public class SingleTon {
  private SingleTon(){}
    private static SingleTon instance;
    public static SingleTon getInstance(){
        if(instance==null){
            instance=new SingleTon();
        }
        return instance;
    }
}

优点: 延迟加载 缺点: 线程不安全

(2).线程安全版本(同步方法)

public class SingleTon {
    private SingleTon(){}
    private static SingleTon instance;
   //synchronized给静态方法加锁,实际上锁住的是SingleTon 这个class类,意味着其他现在在执行这个
  // getInstance()静态方法时,必须等待class类锁被释放。
    public static synchronized SingleTon getInstance(){
        if(instance==null){ 
            instance=new SingleTon();
        }
        return instance;
    }
}

优点:

  • 线程安全

缺点:

  • 性能不太好,每一次获取实例,都要同步,即使该实例已经创建.

(3).双重检查锁定(double-checked-Locking)

public class SingleTon {
    private SingleTon(){}
    private  volatile  static  SingleTon instance;
    public static  SingleTon getInstance(){
        if(instance==null){ 
            synchronized (SingleTon.class){ //和静态方法一样,也是锁住的class类
                if(instance==null){
                      //1.在堆上分配内存空间存储SingleTon对象
                      //2.实例化instance对象,调用SingleTon构造方法 
                      //3.内存空间返回的地 
                    //址赋 值给instance引用.
                    instance=new SingleTon(); //volatile修饰Instance,禁止指令重排,防止报错
                }
            }
        }
        return instance;
    }
}

优点:

  • 线程安全
  • 性能好:只有第一次创建时需要同步
  • 延迟加载

缺点:

  • 实现复杂:容易出错,需要注意volatile关键字
3.静态内部类(Holder方法)
public class SingleTon {
    private SingleTon(){}
    private static class SingleTonHolder {
        private static SingleTon instance=new SingleTon();
    }
    public static  SingleTon getInstance(){
        return SingleTonHolder.instance;
    }
}

**优点:**
  • 线程安全:JVM类加载机制保证线程安全
  • 延迟加载:静态内部类在第一次使用时才加载
  • 实现简单:代码简洁优雅
  • 性能好:无锁

缺点:

  • 不能传递参数:初始化无法传递参数
4.枚举
// 单例
public enum  SingleTonSix {
    Instance;
    SingleTonSix() {
        System.out.println("init");
    }
    public void print(){
        System.out.println("ffffffffffff");
    }
}

//测试
public static void main(String[] args) {

      // 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统能。
        SingleTonSix singleTonSix1=SingleTonSix.Instance;
        singleTonSix1.print();
        SingleTonSix singleTonSix2=SingleTonSix.Instance;
        singleTonSix2.print();
        SingleTonSix singleTonSix3=SingleTonSix.Instance;
        singleTonSix3.print();
        SingleTonSix singleTonSix4=SingleTonSix.Instance;
        singleTonSix4.print();
    }

优点:

  • 线程安全
  • 实现简单

缺点:

  • 不延迟加载:枚举在类加载时初始化
  • 不够灵活:继承、扩展受限
  • 某些框架不支持:如一些依赖注入框架

二.工厂模式

1.普通工厂模式
public interface Sender {
    public void send();
}

public class MailSender implements Sender{
    @Override
    public void send() {
        System.out.println("this is mail sender");
    }
}

public class SmsSender implements  Sender {
    @Override
    public void send() {
        System.out.println("this is sms sender");
    }
}

public class SendFactoryOne {
    public Sender produce(String type){
        if(type.equals("mail")){
            return  new MailSender();
        }else if(type.equals("sms")){
            return  new SmsSender();
        }else{
            return null;
        }
    }
}

2.工厂方法模式
public class SendFactoryTwo {
    public  Sender produceMail(){
       return new MailSender();
    }
    public  Sender produceSms(){
        return new SmsSender();
    }
}
3.静态工厂方法模式
public class SendFactoryThree {
    public static Sender produceMail(){
       return new MailSender();
    }
    public static Sender produceSms(){
        return new SmsSender();
    }
}

4.抽象工程模式
注意:工程方法模式有个问题,类的创建和扩展必须修改工厂类,这违背了闭包原则,所有用到抽象工厂模式,创建多个工厂类,这样一来,直接增加工厂类就可以了,不需要修改之前的代码。
public interface Provider {
    public Sender produce();
}

public class SendMailFactory implements Provider {
    @Override
    public Sender produce() {
        return new MailSender();
    }
}
public class SendSmsFactory implements Provider {
    @Override
    public Sender produce() {
        return new SmsSender();
    }
}
public class MainTest {
    public static void main(String[] args){
        SendFactoryOne sendFactoryOne=new SendFactoryOne();
        sendFactoryOne.produce("mail");
        sendFactoryOne.produce("sms");

         SendFactoryTwo sendFactoryTwo=new SendFactoryTwo();
         sendFactoryTwo.produceMail();
         sendFactoryTwo.produceSms();

         SendFactoryThree.produceMail();
         SendFactoryThree.produceSms();
         
         Provider provider=new SendMailFactory();
         Sender sender=provider.produce();
         sender.send();

         Provider provider1=new SendSmsFactory();
         Sender sender1=provider1.produce();
         sender1.send();
    }
}

3.观察者模式

类似于邮件订阅,当我们浏览一些博客或者wiki时,当你订阅了改文章,如果后续有更新,会及时通知你,是一种一对多的关系。(www.cnblogs.com/luohanguo/p…

(1) 、定义一个观察者接口

public interface Observer {
    public void update();
}

(2)、定义一个被观察者接口

public interface Observerable {
    public void registerObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notifyObservers();
}

(3).定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可,通知新增一个operation()用于通知所有的观察者。

public class WeChatServer implements Observerable {

   List<Observer>  list=new ArrayList<>();//面向接口编程

    @Override
    public void registerObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        if(!list.isEmpty()){
            list.remove(observer);
        }
    }

    @Override
    public void notifyObservers() {
        for(int i=0;i<list.size();i++){
            list.get(i).update();
        }
    }

    public void operation() {
        notifyObservers();
    }
}

(4)、定义具体观察者,微信公众号的具体观察者为用户User1,User2

public class User1 implements Observer {
    @Override
    public void update() {
        System.out.println(User1.class.toString() +"has received the push message!");
    }
}
public class User2 implements Observer {
    @Override
    public void update() {
        System.out.println(User2.class.toString() +"has received the push message!");
    }
}

(5)、编写一个测试类

public class MainTest {
    public static void main(String[] args){
        WeChatServer server=new WeChatServer();
        User1 user1=new User1();
        User2 user2=new User2();
        server.registerObserver(user1);
        server.registerObserver(user2);
        server.operation();
    }
}

image.png

4.装饰模式

装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现统一接口或者继承同一个父类,装饰对象持有被装饰对象的实例。

(1).Food类,让其他所有食物都来继承这个类

public class Food {
    private String food_name;
    public Food(){

    }
    public Food(String food_name) {
        this.food_name = food_name;
    }
    public String make(){
        return  food_name;
    }
}

(2).Bread类,Cream类,Vegetable类

public class Bread extends Food{
    private Food basic_food;
    public Bread(Food basic_food){
          this.basic_food=basic_food;
    }
    @Override
    public String make() {
        return basic_food.make()+"+面包";
    }
}

public class Cream extends Food {
    private  Food basic_food;

    public Cream(Food basic_food) {
        this.basic_food = basic_food;
    }

    @Override
    public String make() {
        return basic_food.make()+"+奶油";
    }
}

public class Vegetable extends Food {
    private Food basic_food;

    public Vegetable(Food basic_food) {
        this.basic_food = basic_food;
    }

    @Override
    public String make() {
        return basic_food.make()+"+蔬菜";
    }
}

(3).编写一个测试类

public class MainTest {

    public static void main(String[] args){
        Food food=new Food("香肠");
        Bread bread=new Bread(food);
        Cream cream=new Cream(bread);
        Vegetable vegetable=new Vegetable(cream);
        System.out.print("运行结果:"+vegetable.make()+"\n");
    }
}

image.png

(4).Android中装饰模式的简单应用

  • 读取数据

    try{
            // 创建一个基础的文件输入流 - 这是被装饰的核心对象
            FileInputStream fis = new FileInputStream("data.text");

            // 第一层装饰:为它添加缓冲功能,提升批量读取效率
           BufferedInputStream bis = new BufferedInputStream(fis);
            
            byte[] buffer = new byte[1024]; // 创建1KB的缓冲区[6](@ref)
            int bytesRead; // 每次实际读取的字节数
            
            // 循环读取,直到文件末尾(read方法返回-1)
            while ((bytesRead = bis.read(buffer)) != -1) {
                // 将读取到的字节数据转换为字符串并输出
                String content = new String(buffer, 0, bytesRead);
                System.out.print(content);
            }
            
        } catch (IOException e) {
            System.err.println("读取文件时发生错误: " + e.getMessage());
        }

  • 写入数据
public class BufferedOutputExample {
    public static void main(String[] args) {
        // 方法1:传统try-catch-finally
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        
        try {
            // 1. 创建FileOutputStream
            fos = new FileOutputStream("output.txt");
            
            // 2. 使用BufferedOutputStream装饰它
            bos = new BufferedOutputStream(fos);
            
            // 3. 写入数据
            String text = "Hello, BufferedOutputStream!\n";
            bos.write(text.getBytes());
            
            // 4. 刷新缓冲区(重要!)
            bos.flush();
            
            System.out.println("数据写入成功!");
            
        } catch (IOException e) {
            System.err.println("写入文件时出错: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 5. 关闭流(只需关闭最外层的)
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            // 注意:不要同时关闭fos,因为bos.close()会关闭底层流
        }
    }
}

5.适配器模式

(1).类适配器模式(通过继承来实现适配器功能)

我们以ps2与usb的转接为例:(ps2适配器类似于我的电驴插口适配器,USB线是手机充电线) Ps2接口:

public interface Ps2 {
    void isPs2();
}

Usb接口:

public interface Usb {
    void isUsb();
}

Usb接口实现类:Usber

public class Usber implements Usb {
    @Override
    public void isUsb() {

    }
}

适配器:AdapterOne

public class AdapterOne extends Usber implements Ps2{
    @Override
    public void isPs2() {
           isUsb();
    }
}

测试方法:

 public static void main(String[] args){
        //1.类适配,通过继承类适配
        Ps2 p=new AdapterOne();
        p.isPs2();
    }
(2).对象适配器模式(通过组合来实现适配器的功能)

适配器:AdapterTwo

public class AdapterTwo implements Ps2{
    private Usber usber;
    public AdapterTwo(Usber usber) {
        this.usber = usber;
    }
    @Override
    public void isPs2() {
        usber.isUsb();
    }
}

测试方法:

public class MainTest {
    public static void main(String[] args){
        //2.对象适配,通过组合实现
        Ps2 p=new AdapterTwo(new Usber());
        p.isPs2();
    }
}
注意:类适配和对象适配模式中所有的adapter均需要实现Ps2接口
(3).接口适配器模式(通过抽象类来实现)

当一个接口包含很多方法,而子类通常只关心其中一两个时,可以使用一个抽象类作为适配器,为空方法提供默认空实现。这样子类只需继承这个抽象类,并重写感兴趣的方法即可。

目标接口A:

public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
}

A的实现类:Adapter

public abstract class Adapter implements A {
    @Override
    public void a() {

    }

    @Override
    public void b() {

    }

    @Override
    public void c() {

    }

    @Override
    public void d() {

    }

    @Override
    public void e() {

    }
}

继承自Adapter的MyAdapter:

public class MyAdapter extends Adapter {

    @Override
    public void a() {
        super.a();
        System.out.println("实现A方法");
    }

    @Override
    public void b() {
        super.b();
        System.out.println("实现B方法");
    }
}

测试方法:

  public static void main(String[] args){
        //3.接口适配,通过抽象类实现
        A aRealize=new MyAdapter();
        aRealize.a();
        aRealize.b();

    }
    
    
(4).适配器模式在安卓中的应用
  • FragmentStatePagerAdapter的父类PageAdapter是一个抽象类,已经实现了getPageTitle(pos)方法,子类可以按照是否需要这个方法来重写即可,TabLayout和ViewPage+FragmentStatePageAdapter联合使用的时候,就必须要实现getPageTitle方法,如果仅仅只是ViewPage+FragmentStatePageAdapter的时候,可以不用实现getPageTitle方法.

class KnowledgePageAdapter(private val listData:MutableList<KnowledgeData.ChildrenBean>, fm:FragmentManager):FragmentStatePagerAdapter(fm) {
    private  val  fragmentList= mutableListOf<Fragment>()
    init {
       listData.forEach {
           fragmentList.add(KnowledgeItemFragment.getInstance(it.id))
       }
    }
    override fun getCount(): Int {
        return fragmentList.size
    }

    override fun getItem(p0: Int): Fragment {
        return fragmentList.get(p0)
    }
     
    override fun getPageTitle(position: Int): CharSequence? {
        return listData.get(position).name
    }
}

6.策略模式(一个人走楼梯上楼或者走电梯上楼)

这里以加减算法为例: (1).定义抽象策略角色接口:Strategy

public interface Strategy {
     int calc(int num1,int num2);
}

(2).定义加法策略:AddStrategy

public class AddStrategy implements Strategy{
    @Override
    public int calc(int num1, int num2) {
        return num1+num2;
    }
}

(3).定义减法策略:SubStrategy

public class SubStrategy implements Strategy {
    @Override
    public int calc(int num1, int num2) {
        return num1-num2;
    }
}

(4).环境角色:Environment

public class Environment {
    private Strategy strategy;
    public Environment(Strategy strategy) {
        this.strategy = strategy;
    }

    public int calc(int a,int b){
        return strategy.calc(a,b);
    }
}

测试方法:

 public static void main(String[] args){
        Strategy addStrage=new AddStrategy();
        Environment environment=new Environment(addStrage);
        int sum1=environment.calc(10,10);
        System.out.println("Result1:"+sum1);
        Strategy subStrage=new SubStrategy();
        int sum2=subStrage.calc(20,10);
        System.out.println("Result2:"+sum2);
    }
    

7.Builder模式

public class Request {
    private String name;
    private String reason;
    private String days;
    private String groupLeaderInfo;
    private String managerInfo;
    private String departmentHeaderInfo;
    private String customInfo;
    public Request(Builder builder){
         // super();
          this.name=builder.name;
          this.reason=builder.reason;
          this.days=builder.days;
          this.groupLeaderInfo=builder.groupLeaderInfo;
          this.managerInfo=builder.managerInfo;
          this.departmentHeaderInfo=builder.departmentHeaderInfo;
          this.customInfo=builder.customInfo;

    }


    public static class Builder{
        private String name;
        private String reason;
        private String days;
        private String groupLeaderInfo;
        private String managerInfo;
        private String departmentHeaderInfo;
        private String customInfo;

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

        public Builder setReason(String reason) {
            this.reason = reason;
            return this;
        }

        public Builder setDays(String days) {
            this.days = days;
            return this;
        }

        public Builder setGroupLeaderInfo(String groupLeaderInfo) {
            this.groupLeaderInfo = groupLeaderInfo;
            return this;
        }

        public Builder setManagerInfo(String managerInfo) {
            this.managerInfo = managerInfo;
            return this;
        }

        public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
            this.departmentHeaderInfo = departmentHeaderInfo;
            return this;
        }

        public Builder setCustomInfo(String customInfo) {
            this.customInfo = customInfo;
            return this;
        }
        public Builder newRequest(Request request){
            this.name=request.name;
            this.days=request.days;
            this.reason=request.reason;
            if(request.getGroupLeaderInfo()!=null&&!request.getGroupLeaderInfo().equals("")){
                this.groupLeaderInfo=request.groupLeaderInfo;
            }
            if(request.getManagerInfo()!=null&&!request.getManagerInfo().equals("")){
                this.managerInfo=request.managerInfo;
            }
            if(request.getDepartmentHeaderInfo()!=null&&!request.getDepartmentHeaderInfo().equals("")){
                this.departmentHeaderInfo=request.getDepartmentHeaderInfo();
            }
            return this;
        }

        public Request build(){
            return new Request(this);
        }
    }

    public String getName() {
        return name;
    }

    public String getReason() {
        return reason;
    }

    public String getDays() {
        return days;
    }

    public String getGroupLeaderInfo() {
        return groupLeaderInfo;
    }

    public String getManagerInfo() {
        return managerInfo;
    }

    public String getDepartmentHeaderInfo() {
        return departmentHeaderInfo;
    }

    public String getCustomInfo() {
        return customInfo;
    }

    @Override
    public String toString() {
        return "Request{" +
                "name='" + name + '\'' +
                ", reason='" + reason + '\'' +
                ", days='" + days + '\'' +
                ", groupLeaderInfo='" + groupLeaderInfo + '\'' +
                ", managerInfo='" + managerInfo + '\'' +
                ", departmentHeaderInfo='" + departmentHeaderInfo + '\'' +
                ", customInfo='" + customInfo + '\'' +
                '}';
    }
}

测试方法:

  public static void main(String[] args){
       Request request=new Request.Builder()
               .setName("shuijian")
               .setReason("GoHome")
               .setDays("2days")
               .build();
       System.out.println(request.toString());
    }

8.责任链模式

实例场景     在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:     ① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。     ② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。     ③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。

(1).构造Request对象,如:Builder模式中的Request
(2).构造批准结果对象Result
public class Result {
    public boolean isRality;
    public String  info;

    public Result(boolean isRality, String info) {
        this.isRality = isRality;
        this.info = info;
    }

    public boolean isRality() {
        return isRality;
    }

    public void setRality(boolean rality) {
        isRality = rality;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Result{" +
                "isRality=" + isRality +
                ", info='" + info + '\'' +
                '}';
    }
}
(3).定义一个接口,这个接口用于处理Request和获取请求结果Result
public interface Ratify {
    //处理请求
    public Result deal(Chain chain);
    //对request和result封装,用来转发
    interface Chain{
        //获取当前的request
        Request request();
        //转发Request
        Result proceed(Request request);
    }
}

看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。

(4).实现Chain接口的的真正的包装Request和转发功能
public class RealChain implements Ratify.Chain {
    public Request request;
    public List<Ratify> ratifyList;
    public int index;
    /**
     * 构造方法
     *
     * @param ratifyList
     *            Ratify接口的实现类集合
     * @param request
     *            具体的请求Request实例
     * @param index
     *            已经处理过该request的责任人数量
     */
    public RealChain(List<Ratify> ratifyList, Request request,int index) {
        this.request = request;
        this.ratifyList = ratifyList;
        this.index = index;
    }
    /**
     * 方法描述:具体转发功能
     */
    @Override
    public Result proceed(Request request) {
        Result proceed=null;
        if(ratifyList.size()>index){
          RealChain realChain=new RealChain(ratifyList,request,index+1);
          Ratify ratify=ratifyList.get(index);
          proceed=ratify.deal(realChain);
        }
        return proceed;
    }

    /***
     * 方法描述:返回当前Request对象或者返回当前进行包装后的Request对象
     * @return
     */
    @Override
    public Request request() {
        return request;
    }
}
(5).GroupLeader、Manager和DepartmentHeader,并让他们实现Ratify接口
public class GroupLeader implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("GroupLeader====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>1){
            //包装新的Request对象
            Request newRequest=new Request.Builder().newRequest(request).setGroupLeaderInfo(request.getName()+"平时表现不错,而且现在项目不忙").build();
            return chain.proceed(newRequest);
        }
        return new Result(true,"GroupLeader:早去早回");
    }
}
public class Manager implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("Manager====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>3){
            //构建新的Request
            Request newRequest=new Request.Builder().newRequest(request).setManagerInfo(request.getName()+"每月的KPI考核还不错,可以批准").build();
            return chain.proceed(newRequest);

        }
        return new Result(true,"Manager:早点把事情办完,项目离不开你");
    }
}
public class DepartmentHeader implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("DepartmentHeader=====>request:"+request.toString());
        if(Integer.parseInt(request.getDays())>7){
              return  new Result(false,"DepartmentHeader:你这个时间太长,不能批准");
        }
        return new Result(true,"DepartmentHeader:不要着急,把事情处理完在回来!");
    }
}
public class CustomInterceptor implements Ratify {
    @Override
    public Result deal(Chain chain) {
        Request request=chain.request();
        System.out.println("CustomInterceptor====>"+request.toString());
        String reason=request.getReason();
        if(reason!=null&&reason.equals("事假")){
              Request newRequest=new Request.Builder().newRequest(request).setCustomInfo(request.getName()+"请的是事假,而且很着急,请领导重视一下").build();
              System.out.println("CustomInterceptor====>转发请求");
              return chain.proceed(newRequest);
        }
        return new Result(true,"同意请假");
    }
}
(6).责任链模式工具类
public class ChainOfResponsibilityClient {
    private ArrayList<Ratify> ratifies;

    public ChainOfResponsibilityClient() {
        ratifies=new ArrayList<>();
    }

    /**
     * 为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
     * @param ratify
     */
    public void addRatifys(Ratify ratify){
        ratifies.add(ratify);
    }

    /***
     *
     * 方法描述:执行请求
     * @param request
     * @return
     */

    public Result execute(Request request){
        ArrayList<Ratify> arrayList=new ArrayList<>();
        arrayList.addAll(ratifies);
        arrayList.add(new GroupLeader());
        arrayList.add(new Manager());
        arrayList.add(new DepartmentHeader());
        RealChain realChain=new RealChain(arrayList,request,0);
        return realChain.proceed(request);
    }
}
(6).测试方法
 public static void main(String[] args){
        //写法一
        Request.Builder builder=new Request.Builder();//通过静态内部类构建builder对象
        builder.setName("zhangsan");
        builder.setDays("5");
        builder.setReason("事假");
        Request request=builder.build();//build方法返回request对象
        //写法二
        Request request1=new Request.Builder().setName("lisi").setDays("7").setReason("事假").build();
        //System.out.print("结果:"+request.toString());

        ChainOfResponsibilityClient client=new ChainOfResponsibilityClient();
        //添加自定义的拦截器到责任人列表顶端
        client.addRatifys(new CustomInterceptor());
        Result result=client.execute(request);
        System.out.println("结果:"+result.toString());

    }

9.享元模式

(1).定义一个接口作为享元角色

public interface IBike {
    void ride(int hours);
}

(2).实现IBike接口,作为具体的享元角色

public class ShareBike implements IBike{
    private int price=2 ;

    @Override
    public void ride(int hours) {
        int total=2*hours;
        System.out.println("ride bike total spend "+total+" RMB");

    }
}

(3).创建享元工厂

public class ShareBikeFactory {
    Map<String,IBike> pool=new HashMap<>();
    public  IBike getBike(String name){
        IBike iBike=null;
        if(!pool.containsKey(name)){
            iBike=new ShareBike();
            pool.put(name,iBike);
            System.out.println("交了199元押金,可以用车:"+name);
        }else{
            iBike=pool.get(name);
            System.out.println("押金已交,直接用车:"+name);
        }
        return iBike;
    }
}

(4).测试类

 public static void main(String[] args) {
        ShareBikeFactory shareBikeFactory=new ShareBikeFactory();
        //第一次骑ofo,交押金
        IBike ofo1=shareBikeFactory.getBike("ofo");
        ofo1.ride(2);
        //第一次骑mobike,交押金
        IBike mobike=shareBikeFactory.getBike("mobike");
        mobike.ride(3);
        //第二次骑mobike,不交押金
        IBike ofo2=shareBikeFactory.getBike("ofo");
        ofo2.ride(4);
    }

10.模板方法模式

(1).创建抽象类,定义算法框架

public abstract class Postman {

    public final void post(){//这里声明为final,不希望子类覆盖这个方法,防止更改流程
        prepare();
        call();
        if(isSign()){
            sign();
        }else{
            refuse();
        }
    }

    protected void refuse() {
    }

    protected void sign() {
        System.out.println("派送完毕,客户已经签收!");
    }

    protected boolean isSign() {
        return true;
    }

    protected abstract void call();

    protected void prepare() {
        System.out.println("快递已经到达,准备派送...");
    }
}

需要注意的是上面的抽象类(Postman)包含了三种类型的方法:抽象方法、具体方法和钩子方法。 抽象方法:需要子类去实现。如上面的call()。 具体方法:抽象父类中直接实现。如上面的prepare()和sign()。 钩子方法:有两种,第一种,它是一个空实现的方法,子类可以视情况来决定是否要覆盖它,如上面的refuse();第二种,它的返回类型通常是boolean类型的,一般用于对某个条件进行判断,如果条件满足则执行某一步骤,否则将不执行,如上面的isSign()。 (2).创建具体实现类,定义算法框架 PostmanA:

public  class PostmanA extends Postman{
    @Override
    protected void call() {
        System.out.println("联系收货人A,准备派送...");
    }
}

PostmanB:

public  class PostmanB extends Postman{
    @Override
    protected void call() {
        System.out.println("联系收货人B,准备派送...");
    }

    @Override
    protected boolean isSign() {
        return false;
    }

    @Override
    protected void refuse() {
        super.refuse();
        System.out.println("商品与实物不符,拒绝签收!");
    }
}

(3).测试类

 public static void main(String[] args){
        //A收货人正常签收
        Postman postmanA=new PostmanA();
        postmanA.post();
        //B收货人拒绝签收
        Postman postmanB=new PostmanB();
        postmanB.post();
    }

image.png

11.备忘录模式

以游戏存档为例: (1).创建发起人角色:Game

public class Game {
    private int mLevel=0;
    private int mIcon=0;

    /***
     * 开始游戏
     */
    public void paly(){
        System.out.print("升级了");
        mLevel++;
        System.out.println("当前等级为:"+mLevel);
        mIcon+=32;
        System.out.println("获得金币:"+mIcon);
        System.out.println("当前金币数量为:"+mIcon);
    }

    /***
     * 退出游戏
     */
    public void exit(){
        System.out.println("退出游戏,属性为:等级="+mLevel+",金币="+mIcon);
    }

    //创建备忘录
    public Memo createMemo(){
        Memo memo=new Memo();
        memo.setmLevel(mLevel);
        memo.setmIcon(mIcon);
        return memo;
    }

    public void setMemo(Memo memo){
        mLevel=memo.getmLevel();
        mIcon=memo.getmIcon();
    }

}

(2).创建备忘录角色:Memo

public class Memo {
    private int mLevel;//等级
    private int mIcon;//金币数量

    public int getmLevel() {
        return mLevel;
    }

    public void setmLevel(int mLevel) {
        this.mLevel = mLevel;
    }

    public int getmIcon() {
        return mIcon;
    }

    public void setmIcon(int mIcon) {
        this.mIcon = mIcon;
    }
}

(3).创建负责人角色:CreateMemo

public class CreateMemo {
    private Memo memo;

    public Memo getMemo() {
        return memo;
    }

    public void setMemo(Memo memo) {
        this.memo = memo;
    }
}

(4).测试类

public static void main(String[] args){
        Game game=new Game();
        game.paly();
        CreateMemo createMemo=new CreateMemo();
        createMemo.setMemo(game.createMemo());//游戏存档
        game.exit();
        //第二次进入游戏
        System.out.println("第二次进入游戏");
        Game secondGame=new Game();
        secondGame.setMemo(createMemo.getMemo());//取出之前备忘录中的数据
        secondGame.paly();
        secondGame.exit();
    }

12.原型模式

(1).创建具体原型类 实现Cloneable接口:

public class Card implements Cloneable {
    private int num;//卡号
    private Spec spec=new Spec();
    public Card(){
        System.out.println("Card 执行构造函数");
    }

    @Override
    protected Card clone() throws CloneNotSupportedException {
        System.out.println("clone时不执行构造函数");
        Card card= (Card) super.clone();
        card.spec=spec.clone();//对Spce对象也调用clone,实现深拷贝
        return card;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public Spec getSpec() {
        return spec;
    }

    public void setSpec(int width,int  length) {
        spec.width=width;
        spec.length=length;
    }

    public class Spec implements Cloneable{
        private int width;
        private int length;

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public int getLength() {
            return length;
        }

        public void setLength(int length) {
            this.length = length;
        }

        @Override
        protected Spec clone() throws CloneNotSupportedException {
            return (Spec) super.clone();
        }
    }

    @Override
    public String toString() {
        return "Card{" +
                "num=" + num +
                ", spec=" +"{width="+spec.getWidth()+",length="+spec.getLength()+
                '}';
    }
}

(2).测试类

 public static void main(String[] args) throws CloneNotSupportedException {
        Card card1=new Card();
        card1.setNum(111);
        card1.setSpec(66,67);
        System.out.println(card1.toString());
        System.out.println("---------------------");
        //拷贝
        Card card2=card1.clone();
        System.out.println(card2.toString());
        System.out.println("---------------------");
        //拷贝之后,card2对num进行重新赋值
        card2.setNum(222);
        System.out.println(card1.toString());
        System.out.println(card2.toString());
        System.out.println("---------------------");
        //拷贝之后,card2对Spec进行重新赋值之后,连card1也跟着改变了,这种就是浅拷贝
        card2.setSpec(76,77);
        System.out.println(card1.toString());
        System.out.println(card2.toString());
        System.out.println("---------------------");
    }

image.png

13.命令模式

(1).创建命令接口Command

public interface Command {
    void execute();
}

(2).创建命令接口实现类:ShutDownCommand

public class ShutDownCommand implements Command {
    Receiver receiver;

    public ShutDownCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        System.out.println("命令角色执行关机命令");
        receiver.action();
    }
}

(3).创建命令执行者Receiver

public class Receiver {
    public void action(){
        System.out.println("接收者执行具体的操作");
        System.out.println("开始执行关机命令");
        System.out.println("退出所有程序");
        System.out.println("关机...");
    }
}

(4).创建调用者Invoker

public class Invoker {
    private  Command command;
    public Invoker(Command command) {
        this.command = command;
    }
    public void action(){
        System.out.println("调用者执行命令");
        command.execute();
    }
}

测试方法:

public static void main(String[] args){
       Receiver receiver=new Receiver();//创建命令接收者
       Command command=new ShutDownCommand(receiver);//创建一个命令的具体实现对象,并指定命令接收者
       Invoker invoke=new Invoker(command);//创建一个命令调用者,并指定具体命令
       invoke.action();
    }
注意:此处调用者与接受者之间的解藕。易于扩展,扩展命令只需新增具体命令类即可,符合开放封闭原则。

image.png

14.代理模式

(1).静态代理 IBuy接口

public interface IBuy {
    void buy();
}

IBuy接口实现类:Home,OverSea

public class Home implements IBuy {
    @Override
    public void buy() {
        System.out.println("国内要买一个包");
    }
}
public class Oversea implements IBuy {
    IBuy buyer;
    public Oversea(IBuy buyer) {
        this.buyer=buyer;
    }

    @Override
    public void buy() {
        System.out.println("我是海外代购");
        buyer.buy();
    }
}

测试方法:

  public static void main(String[] args){
        //静态代理
        IBuy home=new Home();
        IBuy oversea=new Oversea(home);
        oversea.buy();
        System.out.println("----------------------------------------");
        
    }

(2).动态代理(代理类在程序运行时动态生成) 动态代理类:DynamicProxy

public class DynamicProxy implements InvocationHandler {
    private Object obj;//被代理的对象
    public DynamicProxy(Object obj) {
        this.obj=obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("海外动态代理调用方法:"+method.getName());
        Object result=method.invoke(obj,args);
        return result;
    }
}

测试方法:

// 动态代理
public static void main(String[] args) {
  IBuy home = new Home(); // 1. 创建被代理的真实对象
  ClassLoader classLoader = home.getClass().getClassLoader(); 
  // 3. 获取真实对象实现的所有接口
  Class[] classes = new Class[]{IBuy.class}; 
  // 4. 创建InvocationHandler,并传入真实的对象 
  DynamicProxy dynamicProxy = new DynamicProxy(home); 
  // 5. 动态创建代理对象
  IBuy oversea1 = (IBuy) Proxy.newProxyInstance(classLoader, classes, dynamicProxy);
  oversea1.buy(); // 6. 通过代理对象调用方法
  System.out.println("----------------------------------------");
}

image.png