暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

设计模式(02)

爱德华的奇妙生活 2020-06-22
207

9


原型模式


9.1

克隆


以某个对象为原型,从而复制出新的对象,新的对象与原来的对象是一模一样的,这样在创建的对象的时候,可以提高效率,和new类似,都是用来创建一个新的对象的方式,但是与new不同的是,克隆得到的对象相当于是原来对象的一个副本,在副本上进行各种操作不会影响到原来对象。

    package com.zhang.prototype;


    import java.util.Date;
    /*
    1.实现一个接口 Cloneable
    2.重写一个方法 clone()
    * */


    //video
    public class Video implements Cloneable{ //无良up,克隆别人的视频
    private String name;
    private Date createTime;


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


    public Video() {
    }


    public Video(String name, Date createTime) {
    this.name = name;
    this.createTime = createTime;
    }


    public String getName() {
    return name;
    }


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


    public Date getCreateTime() {
    return createTime;
    }


    public void setCreateTime(Date createTime) {
    this.createTime = createTime;
    }


    @Override
    public String toString() {
    return "Video{" +
    "name='" + name + '\'' +
    ", createTime=" + createTime +
    '}';
    }
    }
      package com.zhang.prototype;


      import javax.xml.crypto.Data;
      import java.util.Date;


      /*
      客户端:克隆
      * */
      public class CloneVideo {
      public static void main(String[] args) throws CloneNotSupportedException {
      // 原型对象 video1
      Date date = new Date();
      Video video1 = new Video("原型视频",date);


      System.out.println("video1-----"+video1);
      System.out.println("video1-hashcode----"+video1.hashCode());


      // video1 克隆 video2 原来是通过new的方式 Video video2 = new Video("原型视频",date);
      Video video2 = (Video) video1.clone();


      System.out.println("video1-----"+video2);
      System.out.println("video1-hashcode-----"+video2.hashCode());
      }
      }
      上述实现克隆的方式是一种浅克隆方式,即video1与video2同时指向了同一个Date,如果修改这个Date值,video1与video2会同时发生更改,但这不是我们想要的结果,我们想要的是深克隆的结果,即新克隆出来的video2拥有自己的Date空间,深克隆可以通过序列化和反序列化来得到,同时也可以通过改造clone方法来实现。
        package com.zhang.prototype.demo02;


        import java.util.Date;
        /*
        1.实现一个接口 Cloneable
        2.重写一个方法 clone()
        * */


        //video
        public class Video implements Cloneable{ //无良up,克隆别人的视频
        private String name;
        private Date createTime;


        @Override
        protected Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        //实现深克隆最好的方法,就是对对象的属性也直接进行克隆,但是如果代码量非常的多的情况下,这样的方式也会很麻烦
        // 序列化、反序列化需要和IO打交道,那么效率就会降低
        Video v = (Video)object;
        //将这个对象的属性也进行克隆
        v.createTime = (Date)this.createTime.clone();
        return object;
        }


        public Video() {
        }


        public Video(String name, Date createTime) {
        this.name = name;
        this.createTime = createTime;
        }


        public String getName() {
        return name;
        }


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


        public Date getCreateTime() {
        return createTime;
        }


        public void setCreateTime(Date createTime) {
        this.createTime = createTime;
        }


        @Override
        public String toString() {
        return "Video{" +
        "name='" + name + '\'' +
        ", createTime=" + createTime +
        '}';
        }
        }
          package com.zhang.prototype.demo02;


          import java.util.Date;




          public class CloneVideo {
          public static void main(String[] args) throws CloneNotSupportedException {


          //原型对象video1
          Date date = new Date();
          Video v1 = new Video("原型视频",date);
          Video v2 = (Video)v1.clone();


          System.out.println("v1===="+v1);
          System.out.println("v2===="+v2);


          System.out.println("v1===========v2");
          date.setTime(33131445);


          System.out.println("v1===="+v1);
          System.out.println("v2===="+v2);
          }
          }

          Spring中Bean的创建有两种,一种是单例模式,另一种是原型模式。


          10


          适配器模式

            package com.zhang.adapter;


            //要被适配的类:网线
            public class Reticle {


            public void request(){
            System.out.println("我要用网线上网");
            }
            }

              package com.zhang.adapter;


              //接口转换器的抽象实现
              public interface NetToUsb {
              // 作用:处理请求,网线连接USB
              public void handleRquest();


              }
                package com.zhang.adapter;


                //真正的适配器,一段连接电脑,一段连接网线
                public class AadpterReal extends Reticle implements NetToUsb {


                @Override
                public void handleRquest() {
                super.request(); //可以使用网线上网了
                }
                }
                  package com.zhang.adapter;


                  //1.继承(类适配器,单继承)
                  //2.组合(对象适配器,常用)
                  //客户端类:向上往,但是是MacBook,无法直接插网线
                  public class Computer {


                  //电脑需要连接转接器才可以上网
                  public void net(NetToUsb adapterreal){
                  //上网的具体实现,现在需要适配器转接头来连接网线
                  adapterreal.handleRquest();
                  }


                  public static void main(String[] args) {
                  //电脑,适配器,网线
                  Computer computer = new Computer();
                  Reticle reticle = new Reticle();
                  AadpterReal adpterReal = new AadpterReal();


                  computer.net(adpterReal);
                  }
                  }

                  使用组合的方式创建适配器

                    package com.zhang.adapter;


                    public class Adapter02 implements NetToUsb{

                    private Reticle reticle;

                    public Adapter02(Reticle reticle){
                    this.reticle = reticle;
                    }
                    @Override
                    public void handleRquest() {
                    reticle.request(); //可以上网了
                    }
                    }
                      package com.zhang.adapter;


                      //1.继承(类适配器,单继承)
                      //2.组合(对象适配器,常用)
                      //客户端类:向上往,但是是MacBook,无法直接插网线
                      public class Computer {


                      //电脑需要连接转接器才可以上网
                      public void net(NetToUsb adapterreal){
                      //上网的具体实现,现在需要适配器转接头来连接网线
                      adapterreal.handleRquest();
                      }


                      public static void main(String[] args) {
                      //电脑,适配器,网线
                      Computer computer = new Computer();
                      Reticle reticle = new Reticle();
                      Aadpter02 adpterReal = new Aadpter02(reticle);


                      computer.net(adpterReal);
                      }
                      }

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

                      角色分析:

                      • 目标接口:客户所期待的接口,目标可以是具体的或抽象的类,也可以是接口。

                      • 需要适配的类:需要适配的类或适配者类。

                      • 适配器:通过包装一个需要适配的对象,把源接口转换成目标对象。


                      10.1

                      对象适配器优点


                      • 一个对象适配器可以把多个不同的适配者适配到同一个目标

                      • 可以适配一个适配者的子类,由于适配器和适配者之间是关联关系,根据“里氏代换原则”,适配桥接模式子类也可以通过该适配器进行适配


                      10.2

                      类适配器的缺点


                      • 对于Java,C#都不支持多重继承的语言。一次最多只能适配一个适配者类,不能同时适配多个适配者。

                      • 在Java、C#等语言中,类适配器模式中的目标抽象类只能为接口不能为类,其实应有一定的局限性。


                      10.3

                      使用场景


                      • 系统需要使用一些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。

                      • 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。


                      11


                      桥接模式

                      桥接模式就是将抽象部分与他的实现部分分离,使他们都可以独立的变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。

                        package com.zhang.bridge;


                        public interface Brand {
                        void info();
                        }
                          package com.zhang.bridge;


                          //联想品牌
                          public class Lenovo implements Brand {
                          @Override
                          public void info() {
                          System.out.println("联想");
                          }
                          }
                            package com.zhang.bridge;


                            //苹果品牌
                            public class Apple implements Brand {


                            @Override
                            public void info() {
                            System.out.println("苹果");
                            }
                            }
                              package com.zhang.bridge;


                              //抽象的电脑类型
                              public abstract class Computer {
                              //组合 品牌
                              protected Brand brand;
                              public Computer(Brand brand){this.brand=brand;}


                              public void info(){
                              brand.info(); //自带品牌
                              }
                              }


                              class Desktop extends Computer{


                              public Desktop(Brand brand) {
                              super(brand);
                              }


                              @Override
                              public void info() {
                              super.info();
                              System.out.println("台式机");
                              }
                              }


                              class Laptop extends Computer{


                              public Laptop(Brand brand) {
                              super(brand);
                              }


                              @Override
                              public void info() {
                              super.info();
                              System.out.println("笔记本");
                              }
                              }
                                package com.zhang.bridge;


                                public class Test {
                                public static void main(String[] args) {
                                //苹果笔记本
                                Computer computer = new Laptop(new Apple());
                                computer.info();


                                //联想台式机
                                Computer computer1 = new Desktop(new Lenovo());
                                computer1.info();
                                }
                                }

                                11.1

                                好处分析


                                • 桥接模式偶尔类似于多继承方案,但是多继承方案违背了类的单一职责原则,复用性比较差,类的个数也非常多,桥接模式是比多继承方案更好的解决方法,极大地减少了子类的个数,从而降低了管理和维护的成本。

                                • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。符合开闭原则,就像一座桥,可以把两个变化的维度连接起来。


                                11.2

                                劣势分析


                                • 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层要求开发者针对抽象进行设计与编程

                                • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。


                                11.3

                                最佳实践


                                • 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使他们在抽象层建立一个关联关系,抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合。新系统需要对抽象化角色和实现好角色进行动态耦合。

                                • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

                                • 虽然在系统中使用继承是没有关系的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者,对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。


                                11.4

                                场景


                                • java语言通过java虚拟机实现了平台的无关性

                                • AWT中的Peer架构。

                                • JDBC驱动程序也是桥接模式的应用之一。

                                END


                                点击上方“蓝字”关注我们吧!
                                文章转载自爱德华的奇妙生活,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                评论