趁热打铁,紧跟着上一节的工厂方法模式。这一节介绍一下抽象工厂模式,以及分析俩个模式的不同

1、何为抽象模式?

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

在Abstract Factory模式中将会出现抽象工厂,它会将抽象零件组装为抽象产品。也就是说,我们并不关心零件的具体实现,而是只关心接口(API )。我们仅使用该接口( API )将零件组装成为产品。

在Tempate Method模式和Builder模式中,子类这- -层负责方法的具体实现。在Abstract Factory模式中也是一样的。在子类这一层中有 具体的工厂,它负责将具体的零件组装成为具体的产品。

我们赶紧来看看下面这段抽象工厂的示例程序吧。跟着代码看抽象模式!

2、示例程序

效果:

类图:

类的一览表:

类的位置:

2.1 定义抽象的零件 Item类

package cn.design.abstractfactory.factrory;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 9:11
* @Description Item类是Link类和Tray类的父类(Item有 “ 项目 ” 的意思)。这样 Link类和Tray类就具有可替换性了。
*/
public abstract class Item {
   /**
    * caption字段表示项目的“标题”。
    */
   protected String caption;    public Item(String caption) {
       this.caption = caption;
  }    /**
    * makeHTML方法是抽象方法,需要子类来实现这个方法。该方法会返回HTML文件的内容(需要子类去实现)。
    *
    * @return HTML
    */
   public abstract String makeHTML();
}

2.2 定义抽象的零件组成 Link类

package cn.design.abstractfactory.factrory;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 9:14
* @Description Link类(代码清单8 - 2)是抽象地表示HTML的超链接的类。
* 由于Link类中没有实现父类( Item类)的抽象方法(ma keHTML),因此它也是抽象类。
*/
public abstract class Link extends Item {
   /**
    * url字段中保存的是超链接所指向的地址。乍一看,在Link类中好像一个抽象方法都没有,
    * 但实际上并非如此。
    */
   protected String url;    public Link(String caption, String url) {
       super(caption);
       this.url = url;
  }
}

2.3 定义抽象的零件组成 Tray类

package cn.design.abstractfactory.factrory;

import java.util.ArrayList;
import java.util.List; /**
* @author lin
* @version 1.0
* @date 2020-07-17 9:18
* @Description Tray类(代码清单8 - 3)表示的是-一个含有多个Link类和Tray类的容器( Tray有托盘的意
* 思。请想象成在托盘上放置着-一个- -个项目 )。
* 虽然Tray类也继承了Item类的抽象方法makeHTML,但它并没有实现该方法。因此,Tray
* 类也是抽象类。
*/
public abstract class Tray extends Item {
   protected List<Item> tray = new ArrayList<>();    public Tray(String caption) {
       super(caption);
  }    /**
    * Tray类使用add方法将Link类和Tray类集合在- -起。为了表示集合的对象是“Link类
    * 和Tray类”,我们设置add方法的参数为Link类和Tray类的父类Item类。
    *
    * @param item
    */
   public void add(Item item) {
       tray.add(item);
  } }

2.4 定义抽象的产品 Page 类

package cn.design.abstractfactory.factrory;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List; /**
* @author lin
* @version 1.0
* @date 2020-07-17 10:43
* @Description Page类是抽象地表示HTML页面的类。
* 如果将Link和Tray比喻成抽象的“零件”,那么Page类就是抽象的“产品”。
*/
public abstract class Page {
   /**
    * title 和author分别是表示页面标题和页面作者的字段。作者名字通过参数传递给Page类的构造函数。
    */
   protected String title;
   protected String author;
   protected List<Item> content = new ArrayList<>();    public Page(String title, String author) {
       this.title = title;
       this.author = author;
  }    /**
    * 可以使用add方法向页面中增加Item(即Link或Tray)。增加的Item将会在页面中显示出来。
    *
    * @param item 零件
    */
   public void add(Item item) {
       content.add(item);
  }    /**
    * output方法首先根据页面标题确定文件名,接着调用ma keHTML方法将自身保存的HTML
    * 内容写人到文件中。
    * 其中,我们可以去掉如下语句(1 )中的this,将其写为如下语句(2 )那样。
    * writer .write (this . makeHTML()) ;
    * ...... ( 1 )
    * writer . write (makeHTML()) ;
    * ...... (2 )
    * 为了强调调用的是Page类自己的makeHTML方法,我们显式地加上了this。这里调用的
    */
   public void output() {
       try {
           String fileName = title + ".html";
           FileWriter writer = new FileWriter(fileName);
           writer.write(this.makeHTML());
           writer.close();
           System.out.println(fileName + " 编写完成");
      } catch (IOException e) {
           e.printStackTrace();
      }
  }    /**
    * makeHTML方法是一- 个抽象方法。output 方法是一个简单的Template Method模式的方法。
    *
    * @return html 字符串
    */
   public abstract String makeHTML(); }

2.5 定义抽象的工厂 Factory类

package cn.design.abstractfactory.factrory;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 11:00
* @Description TODO
*/
public abstract class Factory {
   /**
    * getFactory 方法通过调用Class类的forName方法来动态地读取类信息,接着使用,
    * newInstance方法生成该类的实例,并将其作为返回值返回给调用者。
    * Class类属于java.lang包,是用来表示类的类。Class 类包含于Java的标准类库中。
    * forName是java.lang.Class的类方法(静态方法),newInstance则是java. lang.
    * Class的实例方法。
    * 请注意,虽然getFactory方法生成的是具体工厂的实例,但是返回值的类型是抽象工厂类型。
    * @param className
    * @return
    */
   public static Factory getFactory(String className) {
       Factory factory = null;
       try {
           factory = (Factory) Class.forName(className).newInstance();
      } catch (InstantiationException | IllegalAccessException e) {
           e.printStackTrace();
      } catch (ClassNotFoundException e) {
           System.out.println("ClassNotFoundException 没有找到 " + className + " 类.");
      }
       return factory;   }
   public abstract Link createLink(String caption, String url);    public abstract Tray createTray(String caption);    /**
    * createLink、createTray. createPage等方法是用于在抽象工厂中生成零件和产品的方
    * 法。这些方法都是抽象方法,具体的实现被交给了Factory类的子类。不过,这里确定了方法的
    * 名字和签名。
    * @param title
    * @param author
    * @return
    */
   public abstract Page createPage(String title, String author);
}

2.6 定义具体的工厂 ListFactory类

package cn.design.abstractfactory.listfactory;

import cn.design.abstractfactory.factrory.Factory;
import cn.design.abstractfactory.factrory.Link;
import cn.design.abstractfactory.factrory.Page;
import cn.design.abstractfactory.factrory.Tray; /**
* @author lin
* @version 1.0
* @date 2020-07-17 11:29
* @Description TODO
*/
public class ListFactory extends Factory {    @Override
   public Link createLink(String caption, String url) {
       return new ListLink(caption, url);
  }    @Override
   public Tray createTray(String caption) {
       return new ListTray(caption);
  }    @Override
   public Page createPage(String title, String author) {
       return new ListPage(title, author);
  }
}

2.7 定义具体的零件 ListLink类

package cn.design.abstractfactory.listfactory;

import cn.design.abstractfactory.factrory.Link;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 11:31
* @Description TODO
*/
public class ListLink extends Link {    public ListLink(String caption, String url) {
       super(caption, url);
  }    @Override
   public String makeHTML() {
       return "<li><a href =\"" + url + "\">" + caption + "</a></li>\n";
  }
}

2.8 定义具体的零件 ListTray类

package cn.design.abstractfactory.listfactory;

import cn.design.abstractfactory.factrory.Item;
import cn.design.abstractfactory.factrory.Tray; import java.util.Iterator; /**
* @author lin
* @version 1.0
* @date 2020-07-17 11:32
* @Description TODO
*/
public class ListTray extends Tray {
   public ListTray(String caption) {
       super(caption);
  }    @Override
   public String makeHTML() {
       StringBuffer buffer = new StringBuffer();
       buffer.append("<li>\n");
       buffer.append(caption + "\n");
       buffer.append("<ul>\n");
       Iterator it = tray.iterator();
       while (it.hasNext()) {
           Item item = (Item) it.next();
           buffer.append(item.makeHTML());
      }
       buffer.append("</ul>\n");
       buffer.append("</li>\n");
       return buffer.toString();   }
}

2.9 定义具体的产品 ListPage类

package cn.design.abstractfactory.listfactory;

import cn.design.abstractfactory.factrory.Item;
import cn.design.abstractfactory.factrory.Page; import java.util.Iterator; /**
* @author lin
* @version 1.0
* @date 2020-07-17 11:34
* @Description TODO
*/
public class ListPage extends Page {
   public ListPage(String title, String author) {
       super(title, author);
  }    @Override
   public String makeHTML() {
       StringBuffer buffer = new StringBuffer();
       buffer.append("<html><head><title>" + title + "</title></head>\n");
       buffer.append("<body>\n");
       buffer.append("<h1>" + title + "</h1>\n");
       buffer.append("<ul>\n");
       Iterator it = content.iterator();
       while (it.hasNext()) {
           Item item = (Item) it.next();
           buffer.append(item.makeHTML());
      }
       buffer.append("</ul>\n");
       buffer.append("<hr><address>" + author + "</address>");
       buffer.append("</body></html>\n");
       return buffer.toString();   }
}

2.10 测试Main类

package cn.design.abstractfactory;

import cn.design.abstractfactory.factrory.Factory;
import cn.design.abstractfactory.factrory.Link;
import cn.design.abstractfactory.factrory.Page;
import cn.design.abstractfactory.factrory.Tray;
import cn.design.abstractfactory.listfactory.ListFactory;
import cn.design.abstractfactory.tablefactory.TableFactory;
import com.alibaba.fastjson.JSON; /**
* @author lin
* @version 1.0
* @date 2020-07-17 9:10
* @Description TODO
*/
public class Main {
   public static void main(String[] args) {
       Factory factory = Factory.getFactory(ListFactory.class.getName());
//       Factory factory = Factory.getFactory(TableFactory.class.getName());        Link people = factory.createLink("人民日报", "http://www.people.com.cn/");
       Link gmw = factory.createLink(" 光明日报", "http://www.gmw.cn/");
       Link usYahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
       Link jpYahoo = factory.createLink("Yahoo!Japan", "http://ww.yahoo.co.jp/");
       Link excite = factory.createLink("Excite", "http://www.excite.com/");
       Link google = factory.createLink("Google", "http://www.google.com/");        Tray trayNews = factory.createTray(" 日报");
       trayNews.add(people);
       trayNews.add(gmw);        Tray trayYaHoo = factory.createTray("Yahoo!");
       trayYaHoo.add(usYahoo);
       trayYaHoo.add(jpYahoo);        Tray traySearch = factory.createTray("检索引擎");
       traySearch.add(trayYaHoo);
       traySearch.add(excite);
       traySearch.add(google);        Page page = factory.createPage("LinkPage", " 发哥讲");
       page.add(trayNews);
       page.add(traySearch);
       page.output();
  }
}

运行效果如开篇效果图

3、改造成table工厂示例

3.1 定义TableFactory类

package cn.design.abstractfactory.tablefactory;

import cn.design.abstractfactory.factrory.Factory;
import cn.design.abstractfactory.factrory.Link;
import cn.design.abstractfactory.factrory.Page;
import cn.design.abstractfactory.factrory.Tray; /**
* @author lin
* @version 1.0
* @date 2020-07-17 14:53
* @Description TODO
*/
public class TableFactory extends Factory {
   @Override
   public Link createLink(String caption, String url) {
       return new TableLink(caption, url);
  }    @Override
   public Tray createTray(String caption) {
       return new TableTray(caption);
  }    @Override
   public Page createPage(String title, String author) {
       return new TablePage(title, author);
  }
}

3.2定义TableLink类

package cn.design.abstractfactory.tablefactory;

import cn.design.abstractfactory.factrory.Link;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 14:54
* @Description TODO
*/
public class TableLink extends Link {
   public TableLink(String caption, String url) {
       super(caption, url);
  }    @Override
   public String makeHTML() {
       return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";   }
}

3.3定义TableTray类

package cn.design.abstractfactory.tablefactory;

import cn.design.abstractfactory.factrory.Item;
import cn.design.abstractfactory.factrory.Tray; import java.util.Iterator; /**
* @author lin
* @version 1.0
* @date 2020-07-17 14:56
* @Description TODO
*/
public class TableTray extends Tray {
   public TableTray(String caption) {
       super(caption);
  }    @Override
   public String makeHTML() {
       StringBuffer buffer = new StringBuffer();
       buffer.append("<td>");
       buffer.append("<table width=\"100%\" border=\"1\"><tr>");
       buffer.append("<td bgcolor=\"#ccccc\" align=\"center\" colspan=\"" + tray.size() + "\"><b>" + caption + "</b></td>");
       buffer.append("</tr>\n");
       buffer.append("<tr>\n");
       Iterator it = tray.iterator();
       while (it.hasNext()) {
           Item item = (Item) it.next();
           buffer.append(item.makeHTML());
      }
       buffer.append("</tr></table>");
       buffer.append("</td>");
       return buffer.toString();   }
}

3.4定义TablePage类

package cn.design.abstractfactory.tablefactory;

import cn.design.abstractfactory.factrory.Item;
import cn.design.abstractfactory.factrory.Page; import java.util.Iterator; /**
* @author lin
* @version 1.0
* @date 2020-07-17 14:57
* @Description TODO
*/
public class TablePage extends Page {
   public TablePage(String title, String author) {
       super(title, author);
  }    @Override
   public String makeHTML() {
       StringBuffer buffer = new StringBuffer();
       buffer.append("<html><head><title>" + title + "</title></head>\n");
       buffer.append("<body>\n");
       buffer.append("<h1>" + title + "</h1>\n");
       buffer.append("<table width=\"80号\" border=\"3\">\n");
       Iterator it = content.iterator();
       while (it.hasNext()) {
           Item item = (Item) it.next();
           buffer.append("<tr>" + item.makeHTML() + "</tr>");
      }
       buffer.append("</table>\n");
       buffer.append("<hr><address>" + author + "</address>");
       buffer.append("</body></html>\n");
       return buffer.toString();   }
}

3.5 测试类

测试类与2.10一样。

使用这个即可

Factory factory = Factory.getFactory(TableFactory.class.getName());

3.6效果

4、分析各个模块的作用

4.1 抽象工厂类图

4.2作用介绍

4.2.1 AbstractProduct (抽象产品)

AbstractProduct角色负责定义AbstractFactory角色所生成的抽象零件和产品的接口( API)。在示例程序中,由Link类、Tray类和Page类扮演此角色。

4.2.2 AbstractFactory (抽象工厂)

AbstractFactory角色负责定义用于生成抽象产品的接口(API)。在示例程序中,由Factory类扮演此角色。

4.2.3 Client (委托者)

Client角色仅会调用AbstractFactory角色和AbstractProduct角色的接口( API)来进行工作,对于具体的零件、产品和工厂- -无所知。在示例程序中,由Main类扮演此角色。图8-9省略了Client这- -角色。

4.2.4 ConcreteProduct (具体产品)

ConcreteProduct角色负责实现AbstractProduct角色的接口( API)。在示例程序中,由以下包中的以下类扮演此角色。

●listfactory包: ListLink类、ListTray类和ListPage类●tablefactory包: TableLink类、TableTray 类和TablePage类

4.2.5 ConcreteFactory (具体工厂)

ConcreteFactory角色负责实现AbstractFactory角色的接口( API)。在示例程序中,由以下包中的以下类扮演此角色。

●listfactory包: Listfactory类●tablefactory 包: Tablefactory类

5、总结

无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。

5.1 抽象工厂模式的优点

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

5.2 抽象工厂模式的缺点

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

5.3 适用场景

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。说的更明白一点,就是一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存

在着一定的关联或者约束,就可以使用抽象工厂模式。假如各个等级结构中的实现类之间不存在关联或约束,则

使用多个独立的工厂来对产品进行创建,则更合适一点。

5.4 对比

抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。

在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。我们依然拿生产汽车的例子来说明他们之间的区别。

自己尝试写着代码区体会。那种方式方便就是用那种,也是根据场景的改变而做出选择!!

6、延伸( 生成实例的方法)

此处作为彩蛋~~~~ 扩展小知识

6.1 new

new 的方式 常用 , 不用多说。

创建一个日期类, 实例:

new Date();

6.2 clone

package cn.design.abstractfactory.clone;

import java.io.Serializable;

/**
* @author lin
* @version 1.0
* @date 2020-07-17 17:02
* @Description TODO
*/
public class User implements Serializable, Cloneable {
   private static final long serialVersionUID = 6695447736493L;
   String name;
   int age;
   Object obj;    public User(String name, int age, Object obj) {
       this.name = name;
       this.age = age;
       this.obj = obj;
  }    public User() {
  }    public User createClone() {
       User user = null;
       try {
           user = (User) super.clone();
      } catch (CloneNotSupportedException e) {
           e.printStackTrace();
      }
       return user;
  }    @Override
   public String toString() {
       return "User{" +
               "name='" + name + '\'' +
               ", age=" + age +
               ", obj=" + obj +
               '}';
  }    public static void main(String[] args) throws CloneNotSupportedException {
       User user = new User("发哥讲", 23, "人逢知己千杯少,难得在漫漫人生路上能认识你");
       System.out.println(user.toString());
       User clone = user.createClone();
       System.out.println("clone: " +clone.toString());
  }
}

clone 包含 浅拷贝和深拷贝, 后续有时间 会出一个专辑,专门介绍

6.3 反射

      Class<?> aClass = Class.forName(User.class.getName());
      Object o = aClass.newInstance();
      System.out.println(o);

反射也是后续会出一个专辑, 通过反射 可以获取到类的所有信息,还有类名,属性,方法上的注解.

自定义注解也是一个高级进阶专题的,放心各位,都不会少!!!

发哥讲

如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~

● 扫码关注公众号

5、抽象工厂 abstract factory 将关联组件组成产品 创建型模式的更多相关文章

  1. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  2. 工厂模式[3] 抽象工厂 Abstract Factory

    简介 1.简单工厂,或静态工厂,产品接口 定义:专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类或实现同一接口 优点:客户端可以直接消费产品,而不必关心具体产品的实现(不关心对象的 ...

  3. 面向对象设计——抽象工厂(Abstract Factory)模式

    定义 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类.抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么.这样一来,客户就能从具体的产 ...

  4. 设计模式四: 抽象工厂(Abstract Factory)

    简介 抽象工厂模式是创建型模式的一种, 与工厂方法不同的是抽象工厂针对的是生产一组相关的产品, 即一个产品族. 抽象工厂使用工厂方法模式来生产单一产品, 单一产品的具体实现分别属于不同的产品族. 抽象 ...

  5. C2:抽象工厂 Abstract Factory

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 应用场景: 一系列相互依赖的对象有不同的具体实现.提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合 UM ...

  6. 设计模式——抽象工厂(Abstract Factory)

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类. ——DP UML类图 模式说明 抽象工厂与工厂方法在定义上最明显的区别是“创建一系列相关或相互依赖对象的接口”,由此可以看出抽象工 ...

  7. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  8. 【设计模式】——抽象工厂Abstract Factory

    模式意图 提供对象的使用接口,隐藏对象的创建过程. 模式结构 AbstractFactory 提供创建对象的接口. ConcreteFactory 提供真正创建对象的实现类,用于组合并创建不同的对象, ...

  9. Headfirst设计模式的C++实现——抽象工厂(Abstract Factory)

    Dough.h #ifndef _DOUGH_H #define _DOUGH_H class Dough { }; #endif ThinCrustDough.h #ifndef _THIN_CRU ...

随机推荐

  1. IOS中input键盘事件keyup 的兼容解决办法

    用input监听键盘keyup事件,在安卓手机浏览器中是可以的,但是在ios手机浏览器中很慢,用输入法输入之后,并未立刻相应keyup事件. 解决办法: 在ios设备上可以用html5的input事件 ...

  2. Go的100天之旅-02基本语法

    基本语法 Go关键字 下面是Go的25个关键字: break default func interface select case defer go map struct chan else goto ...

  3. 使用 maven 创建项目模板

    前言 配置 demo 工程 生成模板 生成项目 上传模板到仓库 参看链接 前言 微服务的概念越来越流行,随着服务粒度越来越细,拆分的模块越来越明确,我们的工程项目也变得越来越多. 有时候一个项目搭建, ...

  4. 3c数码商城

    目标:2020样卷 已完成:增删改查 未完成:有些小知识点不在意丢失,因此导致有些未完善 解决方案:写代码时不要走心,专心一点,减少失误,减少时间,增加效率,使自己的项目看起来更优秀,注意小知识的掌握 ...

  5. integrator.setTimeout 设置一个超时时间,超过这个时间之后,扫描的 Activity 将会被 finish 。

    integrator.setTimeout 设置一个超时时间,超过这个时间之后,扫描的 Activity 将会被 finish . +++++++++++++++++++ 经查,没有这个功能

  6. 日志分析-利用grep,awk等文本处理工具完成(2019-4-9)

    0x00 基础日志分析命令 1. tail - 监控末尾日志的变化 $tail -n 10 error2019.log #显示最后10行日志内容 $tail -n +5 nginx2019.log # ...

  7. 风速风向 UV 相互转换

    这里以c#为例将风的uv分量转成风向风速(别的语言类似) 风向是以y轴正方向为零度顺时针转 UV转风速风向 1 double v ;//v分量 2 double u;//u分量 3 double fx ...

  8. centos7 离线安装paramiko

    离线安装paramiko   1. 利用yum下载paramiko依赖的rpm软件包 安装yum-utils yum -y install yum-utils yumdownloader python ...

  9. Fortify Audit Workbench 笔记 Password Management: Password in Configuration File(明文存储密码)

    Password Management: Password in Configuration File(明文存储密码) Abstract 在配置文件中存储明文密码,可能会危及系统安全. Explana ...

  10. Day15_用户注册

    学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 0.学习 ...