结构型模式

来源:互联网 发布:sql学生成绩表 编辑:程序博客网 时间:2024/06/13 08:23

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
适配器模式:
  Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。就像给不兼容的类套一层壳,实现兼容通用。当然大致思想是这样,实现方式可以有多种。

package DesignMode.Adapter;//抽象访问者interface View{    void Communication();}//经常使用的访问者class OldView implements View {    @Override    public void Communication()    {        System.out.println("Communication success !");    }}//新引进的访问者class NewView{    public void Communication()    {        System.out.println("Communication success too !");    }}//适配器类class Adapter implements View{    NewView newView;    public Adapter(NewView newView)    {        this.newView=newView;    }    @Override    public void Communication()    {        newView.Communication();        }}public class MyAdapter{    public static void main(String[] args)    {        //test1        View view=new OldView();        view.Communication();        System.out.println("---------------------------");        //test2        //Error        //View nowView=new NewView();        View nowView=new Adapter(new NewView());        nowView.Communication();    }}

装饰器模式:
  动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。

设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。

  而使用装饰器模式可以将扩展抽象成一个一个元件,可以多次多处去复用。

package DesignMode;// 抽象方式abstract class Style{    private String styleName = "";    public String getStyleName()    {        return styleName;    }    public void setStyleName(String styleName)    {        this.styleName = styleName;    }    abstract void goSchool();}// 一般的调用方式class Student extends Style{    private String name;    public Student()    {        name = "学生小明 ";    }    @Override    void goSchool()    {        System.out.println(name + super.getStyleName() + " 去学校 !");    }}// 扩展单元1class Bicycle extends Student{    public Bicycle(Style style)    {        super.setStyleName(style.getStyleName() + "骑着自行车 ");    }}// 扩展单元2class Speed extends Student{    public Speed(Style style)    {        super.setStyleName(style.getStyleName() + "以非常快的速度 ");    }}// 测试public class MyDecorator{    public static void main(String[] args)    {        // 普通调用        Student stu = new Student();        stu.goSchool();        // 组合1        Student stu1 = new Bicycle(stu);        stu1.goSchool();        // 组合2        Student stu2 = new Speed(new Bicycle(stu));        stu2.goSchool();        // 组合3        Student stu3 = new Bicycle(new Speed(stu));        stu3.goSchool();    }}

外观模式:
  即门面模式,大管家模式。现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统。然而过多的子系统使得外界客户端与之交互起来十分复杂,解决这种不便的方法便是引进门面模式,一个细化之后复杂的系统可以设置一个接待员的位置,由接待员负责与各个子模块打交道等。这个接待员就是门面模式的体现,外界客户端只接触接待员,由接待员与各个子模块打交道。
  在门面模式中,通常只需要一个门面类,并且此门面类只有一个实例,换言之它是一个单例类。当然这并不意味着在整个系统里只有一个门面类,而仅仅是说对每一个子系统只有一个门面类。或者说,如果一个系统有好几个子系统的话,每一个子系统都有一个门面类,整个系统可以有数个门面类。

package DesignMode.Manager;//复杂的类class Factory{    //众多的元素   protected String elementIce= Ice();   protected String elementThunder=Thunder();   protected String elementFire=fire();   //私有化方法   private String fire()   {       return "火元素 ";   }   private String Thunder()   {       return "雷元素 ";   }   private String Ice()   {       return "冰元素 ";   }}//外观类(大管家类/门面类) class Manager extends Factory{    //众多的组合方式    public void getFirePerson()    {        System.out.println("召唤小火人需要切换"+elementIce+elementIce+elementFire);    }    public void getBlade()    {        System.out.println("召唤刀片需要切换"+elementIce+elementThunder+elementFire);    }    public void getMeteorolite()    {        System.out.println("召唤陨石需要切换"+elementFire+elementFire+elementThunder);    }}//外界访问客户端public class Client{    public static void main(String[] args)    {        Manager manager=new Manager();        manager.getBlade();        manager.getMeteorolite();        manager.getFirePerson();    }}

桥接模式:
  在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
  这个模式很像装饰器模式,区别在于他侧重的是2个或者多个维度的变化。

package DesignMode.Bridge;//修饰簇abstract class Adj{     protected String style;    abstract String getStyle();}class Beautiful extends Adj{    @Override    String getStyle()    {        return "美丽的";    }}class Great extends Adj{    public Great()    {        super.style="高雅的";    }    @Override    String getStyle()    {        return super.style;    }}//礼物簇abstract class Gift{   protected  String category;    protected   Adj adj;    abstract void show();}class Flower extends Gift{    public Flower(Adj adj)    {        this.adj=adj;        this.category="花";    }    public void show()    {        System.out.println(adj.getStyle()+this.category);    }}class Ring extends Gift{    public Ring(Adj adj)    {        this.adj=adj;        this.category="戒指";    }    public void show()    {        System.out.println(adj.getStyle()+this.category);    }}public class MyBridge{    public static void main(String[] args)    {        //test1        Gift flower=new Flower(new Beautiful());        flower.show();        //test2        Gift ring=new Ring(new Great());        ring.show();    }}

组合模式:
  什么情况下使用组合模式
  引用大话设计模式的片段:“当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。”

package DesignMode.group;import java.util.ArrayList;import java.util.List;public class MyGroup{    public abstract class Person    {       protected String name;       protected List<Person> list;        abstract void action();        abstract void add(Person person);        abstract void del(Person person);    }    // 老总(+有下属的员工)    public class Boss extends Person    {        public Boss(String name)        {            this.name = name;            list = new ArrayList<Person>();        }        @Override        void action()        {            System.out.print(name + "接到了指示   ");            for (Person person : list)            {                person.action();            }            System.out.println();        }        @Override        void add(Person person)        {            list.add(person);        }        @Override        void del(Person person)        {            list.remove(person);        }    }    // 普通雇员(没有下属)    public class Employee extends Person    {        public Employee(String name)        {            this.name = name;        }        @Override        void action()        {            System.out.print(name + "接到了指示   ");        }        @Override        void add(Person person)        {}        @Override        void del(Person person)        {}    }    public static void main(String[] args)    {        //创建        MyGroup group=new MyGroup();        Person boss=group.new Boss("董事长");        Person assisant=group.new Boss("助理");        Person employee1=group.new Employee("员工1");        Person employee2=group.new Employee("员工2");        //组合        assisant.add(employee1);        assisant.add(employee2);        boss.add(assisant);        //访问1        employee1.action();        System.out.println();        //访问2        assisant.action();        //访问3        boss.action();    }}

  
共享元模式:
  解释一下概念:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。比如说一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么就大大节约了资源。

package DesignMode.share;import java.util.HashMap;class Hero{   private String name = "";    public Hero(String name)    {        this.name = name;    }    @Override    public String toString()    {        return name;    }}class HeroFactory{    private HashMap<String, Hero> heroMap = new HashMap<String, Hero>();    public Hero getHero(String name)    {        if (heroMap.get(name) != null)        {            return heroMap.get(name);        }        Hero hero = new Hero(name);        heroMap.put(name, hero);        return hero;    }}public class MyShare{    public static void main(String[] args)    {        HeroFactory factory = new HeroFactory();        Hero coco = factory.getHero("coco");        Hero wow = factory.getHero("wow");        Hero coco2 = factory.getHero("coco");        Hero coco3 = factory.getHero("coco");        Hero es = factory.getHero("es");        Hero th = factory.getHero("th");        System.out.println(factory.heroMap.size());        for (String str :  factory.heroMap.keySet())        {            System.out.println(factory.heroMap.get(str));        }    }}

代理模式:
代理模式分为静态代理和动态代理,常见用于切面编程。
静态代理

 interface Server{    void provideSource();}class Target implements Server{    @Override    public void provideSource()    {        System.out.println("提供餐饮服务");    }}class Proxy  implements Server{    Server server;    public Proxy(Server server)    {       this.server=server;    }    @Override    public void provideSource()    {        System.out.println("先点菜");        server.provideSource();        System.out.println("最后结账");    }}public class Client{    public static void main(String[] args)    {        //未代理之前        Server target=new Target();        target.provideSource();        System.out.println("---------分界线--------");        //代理之后        Server proxy=new Proxy(new Target());        proxy.provideSource();    }}

动态代理
主要分为两种方式
  动态代理可以实现重写任何可以有接口的类的实现方法,并且对使用者透明。比如数据库的连接池,使用者依然可以使用close方法,但是使用代理之后,底层的实现完全可以不关闭而是放入池中。
1.jdkproxy:

public interface PersonService{    public void doFirst();    public String doSecond();    public String doThird(String s);}/** *  JDK  Proxy  要求必须要实现接口 */public class PersonServiceImpl implements PersonService{    public void doFirst()    {        System.out.println("1111111111111111");    }    public String doSecond()    {        System.out.println("222222222222222222");        return "second";    }    public String doThird(String s)    {        System.out.println("3333333333333333333\t"+s);        return "third";    }   }import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyFactory{    //创建代理对象    //返回值  就是代理对象    参数是目标对象    public static Object createProxy(final Object target)    {        return Proxy.newProxyInstance(target.getClass().getClassLoader(),                                         target.getClass().getInterfaces(),                 new InvocationHandler()//回调    句柄                {                    //method 调用的目标方法        args 目标方法中的参数      Object:目标方法的返回值                                     public Object invoke(Object proxy, Method method, Object[] args)                                throws Throwable                    {                        //环绕增强                        System.out.println("方法前日志...");//前置增强                        Object value =  method.invoke(target, args);                        System.out.println("方法后日志...");//后置增强                        return value;                    }                });    }}public class Test{    public static void main(String[] args)    {        PersonService s = (PersonService)ProxyFactory.createProxy(new PersonServiceImpl());//        s.doFirst();        System.out.println(s.doThird("abc"));    }}

2.cglibproxy:

//接口public class PersonServiceImpl{    public void doFirst()    {        System.out.println("1111111111111111");    }    public String doSecond()    {        System.out.println("222222222222222222");        return "second";    }    public String doThird(String s)    {        System.out.println("3333333333333333333\t"+s);        return "third";    }}//代理public class ProxyFactory{    public static Object createProxy(final Object target)    {        //cglib        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(           new MethodInterceptor()           {               public Object intercept(Object proxy, Method method, Object[] args, MethodProxy mp)                   throws Throwable                   {                       System.out.println("进入方法,,,添加日志...");                       if("toString".equals(method.getName()))                       {                           return "haha toString ...";                       }                       return method.invoke(target, args);                   }           }        );        return enhancer.create();//代理对象    }}//测试public class Test{    public static void main(String[] args)    {        PersonServiceImpl psi = (PersonServiceImpl)ProxyFactory.createProxy(new PersonServiceImpl());        System.out.println(psi.doSecond());        System.out.println("-----------------aa-------------------");        Date ss=(Date)ProxyFactory.createProxy(new Date());        System.out.println(ss.toString());        System.out.println(ss.toLocaleString());        System.out.println("------------------ee------------------");        Object createProxy = ProxyFactory.createProxy(new Object());        System.out.println(createProxy.toString());        System.out.println("-------------------ff-----------------");        Collection coll =new ArrayList();        Object createProxy2 = ProxyFactory.createProxy(coll);        System.out.println(createProxy2.toString());    }}

需要导入cglib-nodep-2.1_3.jar aspectjrt.jar aspectjweaver.jar包

0 0