• Java设计模式之结构模式


    一、外观模式

    分析:外观模式是为子系统的一组接口提供一个统一的界面,数据库JDBC连接应用就是外观模式的一个典型例子,
    特点:降低系统的复杂度,增加灵活性。
    结果:代码示例:

    public class DBCompare {
      Connection conn = null;
      PreparedStatement prep = null;
      ResultSet rset = null; 
      try {
         Class.forName( "<driver>" ).newInstance();
         conn = DriverManager.getConnection( "<database>" );
        
         String sql = "SELECT * FROM <table> WHERE <column name> = ?";
         prep = conn.prepareStatement( sql );
         prep.setString( 1, "<column value>" );
         rset = prep.executeQuery();
         if( rset.next() ) {
            System.out.println( rset.getString( "<column name" ) );
         }
      } catch( SException e ) {
         e.printStackTrace();
      } finally {
         rset.close();
         prep.close();
         conn.close();
      }
    }
    -----------------------
    -- 修改后的统一接口
    public class DBCompare {
    
      String sql = "SELECT * FROM <table> WHERE <column name> = ?";  
    
      try {
         Mysql msql=new mysql(sql);
         msql.setString( 1, "<column value>" );
         rset = msql.executeQuery();
         if( rset.next() ) {
            System.out.println( rset.getString( "<column name" ) );
         }
      } catch( SException e ) {
         e.printStackTrace();
      } finally {
         mysql.close();
         mysql=null;
      }
    }

    二、代理模式

    分析:代理模式是比较有用途的一种模式,而且变种多样,用途从小的架构设计到系统的大架构设计基本上都覆盖了,
    为什么需要使用代理模式?一、授权机制(访问权限) 二、某个客户端不能直接操作到那个对象,但又和那个对象有所互动(
    通过中间代理处理这种操作)。
    结果:代码示例:

    -- 定义权限的用户
    public class ForumPermissions implements Cacheable {
    /**
    * Permission to read object.
    */
    public static final int READ = 0;
    
    /**
    * Permission to administer the entire sytem.
    */
    public static final int SYSTEM_ADMIN = 1;
    
    /**
    * Permission to administer a particular forum.
    */
    public static final int FORUM_ADMIN = 2;
    
    /**
    * Permission to administer a particular user.
    */
    public static final int USER_ADMIN = 3;
    
    /**
    * Permission to administer a particular group.
    */
    public static final int GROUP_ADMIN = 4;
    
    /**
    * Permission to moderate threads.
    */
    public static final int MODERATE_THREADS = 5;
    
    /**
    * Permission to create a new thread.
    */
    public static final int CREATE_THREAD = 6;
    
    /**
    * Permission to create a new message.
    */
    public static final int CREATE_MESSAGE = 7;
    
    /**
    * Permission to moderate messages.
    */
    public static final int MODERATE_MESSAGES = 8;
    
    .....
    
    public boolean isSystemOrForumAdmin() {
      return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);
    }
    
    .....
    
    }
    -- 只有管理员才有权限操作
    public class ForumProxy implements Forum {
    
    private ForumPermissions permissions;
    private Forum forum; 
    this.authorization = authorization; 
    
    public ForumProxy(Forum forum, Authorization authorization,
    ForumPermissions permissions)
    {
    this.forum = forum;
    this.authorization = authorization;
    this.permissions = permissions;
    }
    
    .....
    
    public void setName(String name) throws UnauthorizedException,
    ForumAlreadyExistsException
    {
      //只有是系统或论坛管理者才可以修改名称
      if (permissions.isSystemOrForumAdmin()) {
        forum.setName(name);
      }
      else {
        throw new UnauthorizedException();
      }
    }

    三、适配器模式

    说明:适配器模式是将两个不兼容的类纠合在一起使用,同时也属于结构性模式,一个是适配者和宁一个是被适配者两者
    身份结合在一起。
    为何使用?
    我们经常会遇到两个没有关系的类会联系在一起使用,第一个解决方法就是,修改各自的接口类,但是我们没有源代码,或者,我们
    不会为了一个应用修改这个接口类,那这种情况下,就该考虑使用适配器模式
    如何使用?
    用组合和继承的方法去使用该模式
    结果:代码示例:

    -- 两个没有关系的类
    public class SquarePeg{
      public void insert(String str){
        System.out.println("SquarePeg insert():"+str);
      }
    
    }
    
    public class RoundPeg{
      public void insertIntohole(String msg){
        System.out.println("RoundPeg insertIntoHole():"+msg);
    }
    }
    -- 继承关系实现
    public class PegAdapter extends SquarePeg{
    
      private RoundPeg roundPeg;
    
      public PegAdapter(RoundPeg peg)(this.roundPeg=peg;)
    
      public void insert(String str){super.insert(str); roundPeg.insertIntoHole(str);}
    
    }
    
    --第二种方式,通过接口实现的方式
    -- 两个没有联系的接口类
    public interface IRoundPeg{
      public void insertIntoHole(String msg);
    
    }
    
    public interface ISquarePeg{
      public void insert(String str);
    
    }
    -- 实现该接口的方法和熟悉
    public class SquarePeg implements ISquarePeg{
      public void insert(String str){
        System.out.println("SquarePeg insert():"+str);
      }
    
    }
    
    public class RoundPeg implements IRoundPeg{
      public void insertIntohole(String msg){
        System.out.println("RoundPeg insertIntoHole():"+msg);
      }
    }
    -- 适配器模式类,实现两个没有联系的接口类
    public class PegAdapter implements IRoundPeg,ISquarePeg{
    
      private RoundPeg roundPeg;
      private SquarePeg squarePeg;
    
      // 构造方法
      public PegAdapter(RoundPeg peg){this.roundPeg=peg;}
      // 构造方法
      public PegAdapter(SquarePeg peg)(this.squarePeg=peg;)
    
      public void insert(String str){ roundPeg.insertIntoHole(str);}
    
    }

    四、组合模式

    分析:组合模式可以这样理解,在我们程序中常用的js前端的应用,大部分都是树型结构的,而组合模式就相当于
    树型结构的模式,通过迭代器遍历出来。
    组合模式的优势:使客户端调用简单,更容易在组合过程中加入部件属性和方法。
    结果:代码示例:

    ---定义抽象类
    public abstract class Equipment
    {
      private String name; 
      //实价
      public abstract double netPrice();
      //折扣价格
      public abstract double discountPrice();
      //增加部件方法  
      public boolean add(Equipment equipment) { return false; }
      //删除部件方法
      public boolean remove(Equipment equipment) { return false; }
      //注意这里,这里就提供一种用于访问组合体类的部件方法。
      public Iterator iter() { return null; }
      
      public Equipment(final String name) { this.name=name; }
    }
    -- 继承该抽象类
    public class Disk extends Equipment
    {
      public Disk(String name) { super(name); }
      //定义Disk实价为1
      public double netPrice() { return 1.; }
      //定义了disk折扣价格是0.5 对折。
      public double discountPrice() { return .5; }
    }

    五、装饰者模式

    分析:装饰者模式是给对象添加额外的一些职责,就像在墙上刷油漆,使用装饰者模式比生成子类实现的都灵活
    为什么要使用装饰者模式?
    我们通常可以继承来实现功能的拓展,若这些功能的拓展比较多,那么势必生成很多子类,增加系统的复杂性,
    使用装饰者模式可以将一些功能动态的加入,提供了"即插即用"的方法,在程序运行期间可以随时插入新增一些
    功能。
    结果:代码示例

    ----定义接口
    public interface Work
    { 
      public void insert();
    
    }
    
    --接口类的实现
    
    public class SquarePeg implements Work{
      public void insert(){
        System.out.println("方形桩插入");
      }
    }
    
    --装饰者模式额外添加的功能
    public class Decorator implements Work{
    
      private Work work;
      //额外增加的功能被打包在这个List中
      private ArrayList others = new ArrayList();
    
      //在构造器中使用组合new方式,引入Work对象;
      public Decorator(Work work)
      {
        this.work=work;
       
        others.add("挖坑");
    
        others.add("钉木板");
      }
    
      public void insert(){
    
        newMethod();
      }
    
      
      //在新方法中,我们在insert之前增加其他方法,这里次序先后是用户灵活指定的    
      public void newMethod()
      {
        otherMethod();
        work.insert();
    
    
      } 
      public void otherMethod()
      {
        ListIterator listIterator = others.listIterator();
        while (listIterator.hasNext())
        {
          System.out.println(((String)(listIterator.next())) + " 正在进行");
        }
    
      } 
    }

    六、桥接模式

    分析:任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种体现,
    所以,人与人的行为这两个概念也反映了抽象与行为之分。在面向对象设计中,对象概念实际是由属性与行为两个部分组成的,
    属性我们可以认为是一种静止的,是一种抽象,一般情况下,行为是包含在一个对象中的,但是,在有的情况下,
    我们需要将这些行为也进行归类,形成一个总的行为接口,这也是桥接模式的优势。
    为什么使用桥接模式?
    不希望抽象部分和行为有一种固定的绑定联系,而是应该可以动态联系的。
    结果:代码示例:

    -- 抽象接口类
    public abstract class Coffee
    {
       CoffeeImp coffeeImp;

       public void setCoffeeImp() {
         this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
       }

      public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}

       public abstract void pourCoffee();
    }

    public abstract class CoffeeImp
    {
       public abstract void pourCoffeeImp();
    }
    --- 继承类
    public class MediumCoffee extends Coffee
    {
       public MediumCoffee() {setCoffeeImp();}

       public void pourCoffee()
       {
         CoffeeImp coffeeImp = this.getCoffeeImp();
         //我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯
         for (int i = 0; i < 2; i++)
         {

          coffeeImp.pourCoffeeImp();
        }
      
       }
    }
    //大杯
    public class SuperSizeCoffee extends Coffee
    {
       public SuperSizeCoffee() {setCoffeeImp();}

       public void pourCoffee()
       {
         CoffeeImp coffeeImp = this.getCoffeeImp();
         //我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯
         for (int i = 0; i < 5; i++)
         {

          coffeeImp.pourCoffeeImp();
        }
      
       }
    }
    -- 主方法
    public static void main(String[] args){

    MediumCoffee mediumCoffee = new MediumCoffee();
    mediumCoffee.pourCoffee();
    }

    七、享元模式

    分析:享元模式是避免大量拥有相同的小类的开销(如耗费内存),使大家共享一个类(元类)
    为什么使用?
    该模式是提高效率和性能的模式,会大大加快程序的运行速度,应用场合很多,比如你要从数据库读取一系列
    字符窜,这些字符窜是有许多是重复的,因此,将这些字符窜存储在池中。
    结果:代码示例:

    --接口定义
     public interface Flyweight 
    {
      public void operation( ExtrinsicState state );
    }
    
    //用于本模式的抽象数据类型(自行设计)
    public interface ExtrinsicState { }
    
    --实现该接口
    public class ConcreteFlyweight implements Flyweight {
      private IntrinsicState state; 
      
      public void operation( ExtrinsicState state ) 
      { 
          //具体操作
      }
    }
    
    
    -- 享元模式类
    public class FlyweightFactory { 
      //Flyweight pool
      private Hashtable flyweights = new Hashtable(); 
    
      public Flyweight getFlyweight( Object key ) { 
        Flyweight flyweight = (Flyweight) flyweights.get(key); 
        if( flyweight == null ) {
          //产生新的ConcreteFlyweight
          flyweight = new ConcreteFlyweight(); 
          flyweights.put( key, flyweight ); 
        } 
        return flyweight; 
      } 
    } 
    -- 主方法(实现 享元模式)
    public static void main(String[] args)
    {
      FlyweightFactory factory = new FlyweightFactory(); 
    Flyweight fly1 = factory.getFlyweight( "Fred" ); 
    Flyweight fly2 = factory.getFlyweight( "Wilma" );
    }
  • 相关阅读:
    NOIp2014 Day2T3 解方程 秦九韶算法
    Luogu P1082 同余方程 拓展欧几里得
    Luogu P1351 联合权值 前缀和
    [USACO06JAN]冗余路径Redundant Paths 无向图tarjan缩点
    P1073 最优贸易 dp
    LOJ #6279. 数列分块入门 3
    LOJ #6278. 数列分块入门 2
    分块
    字典树Trie
    KMP
  • 原文地址:https://www.cnblogs.com/bwcx1375/p/7684196.html
Copyright © 2020-2023  润新知