Matrix42 - 2016年10月
type: channel
link: http://www.sundeqiang.cn/2016/10
description: Record and Share!
items: GOF23设计模式之:原型模式(ProtoType)
items: GOF23设计模式之:建造者模式
items: GOF23设计模式之:工厂模式
items: 安装Storm集群
items: 搭建ZooKeeper集群
items: Maven
items: GOF23设计模式之:单例模式
items: 设计模式GOF23
items: Java 网络编程
items: Java 其他流

GOF23设计模式之:原型模式(ProtoType)
type: item
date: 2016-10-31T11:59:00+08:00
description: 场景 思考一下:克隆技术是怎样的过程?克隆羊多莉大家还记得吗? javascrip语言中,继承怎么实现?那里面也有prototype,大家还记得吗? 原型模式 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式 就是java中的克隆技术,以某个对象为原型,复制出新的对象.显然, 优势有:效率高(直接克隆,避免了重新执行构造过程步骤) 克隆类似于new,但是不同于new.new创建新的对象属性采用的是默认值.克隆出的对象的属性值完全和原型对象相同.并且克隆出的新对象改变不会影响原型对象.然后再修改克隆对象的值 原型模式实现 Cloneable接口可clone方法 Protype模式中实现起来最困难的地方就是内存复制操作,所幸Java中提供了clone()方法替我们做了绝大部分事情 import java.util.Date; //1997年英国克隆羊多莉 public class Sheep implements Cloneable{ private String name; private Date brithday; public Sheep() { // TODO Auto-generated constructor stub } public Sheep(String name, Date brithday) { super(); this.name = name; this.brithday = brithday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBrithday() { return brithday; } public void setBrithday(Date brithday) { this.brithday = brithday; } //重写Object的clone方法 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } import java.util.Date; public class Client { @SuppressWarnings("deprecation") public static void main(String[] args) throws CloneNotSupportedException { //浅克隆 Date d = new Date(183964743); Sheep s1 = new Sheep("莉莉",d); System.out.println(s1); System.out.println(s1.getName()); System.out.println(d.getTime()); d.setDate(183974743); System.out.println(d.getTime()); Sheep s2 = (Sheep) s1.clone(); System.out.println(s2); System.out.println(s2.getName()); s2.setName("多莉"); System.out.println(s2.getName()); System.out.println(d.getTime()); } } import java.util.Date; //1997年英国克隆羊多莉 public class Sheep implements Cloneable{ private String name; private Date brithday; public Sheep() { // TODO Auto-generated constructor stub } public Sheep(String name, Date brithday) { super(); this.name = name; this.brithday = brithday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBrithday() { return brithday; } public void setBrithday(Date brithday) { this.brithday = brithday; } /…

GOF23设计模式之:建造者模式
type: item
date: 2016-10-28T11:24:00+08:00
description: 场景 我们要建造一个复杂的产品.比如:神州飞船,iphone.这个复杂的产品的创建.有这样一个问题需要处理 装配这些子组件是不是有个步骤问题? 实际开发中,我们所需要的对象构建时,也非常复杂,有很多步骤需要处理时 建造模式的本质 分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)，从而可以构造出复杂的对象,这个模式适用于:某个对象的构建过程复杂的情况 由于实现了构建和装配的解耦,不同的构建器,相同的装配,也可以做出不同的对象相同的构建器,不同的装配顺序也可以做出不同的对象,也就是实现了构建算法、装配算法的解耦,实现了更好的复用 public class AirShip { private OrbitalModule orbitalModule; //轨道舱 private Engine engine; //发动机 private EscapeTower escapeTower; //逃逸塔 public OrbitalModule getOrbitalModule() { return orbitalModule; } public void Launch(){ System.out.println("发射!"); } public void setOrbitalModule(OrbitalModule orbitalModule) { this.orbitalModule = orbitalModule; } public Engine getEngine() { return engine; } public void setEngine(Engine engine) { this.engine = engine; } public EscapeTower getEscapeTower() { return escapeTower; } public void setEscapeTower(EscapeTower escapeTower) { this.escapeTower = escapeTower; } } class OrbitalModule{ private String name; public OrbitalModule() { } public OrbitalModule(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class Engine{ private String name; public Engine() { } public Engine(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class EscapeTower{ private String name; public EscapeTower() { super(); } public EscapeTower(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public interface AirShipBuilder { Engine buildEngine(); OrbitalModule buildOrbitalModule(); EscapeTower buildEscapeTower(); } public class LorindaArishipBuilder implements AirShipBuilder{ @Override public Engine buildEngine() { System.out.println("构建发动机!"); return new Engine("Lorinda发动机"); } @Override public OrbitalModule buildOrbitalModule() { System.out.println("构建轨道舱!"); return new OrbitalModule("Lorinda轨道舱"); } @Override pu…

GOF23设计模式之:工厂模式
type: item
date: 2016-10-26T16:51:00+08:00
description: 工厂模式 实现了创建者和调用者的分离 简单工厂模式 用来产生同一等级结构中的任意产品(对于新增的产品,需要修改已有代码) 工厂方法模式 用来生产同一等级结构中的固定产品(支持增加任意产品) 抽象工厂模式 用来生产不同产品族的全部产品(对于增加新的产品,无能为力;支持增加产品族) 面向对象设计的基本原则 OPC(开闭原则,Open-Close Principle):一个软件的实体应对对扩展开发,对修改关闭 DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程 LOD(迪米特法则,Low of Demeter):只与你直接的朋友通信,而避免和陌生人通信 核心本质 实例化对象,用工厂方法代替new操作 将选择实现类,创建对象同一管理和控制.从而将调用者跟我们的实现类解耦 简单工厂模式(使用的比较多) 简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接收不同的参数来返回不同的对象实例 对于增加的新产品无能为力!不修改代码的话是无法扩展的 Car接口: public interface Car { void run(); } Car的两个子类: public class Audi implements Car{ @Override public void run() { System.out.println("奥迪在跑!"); } } public class Byd implements Car{ @Override public void run() { System.out.println("比亚迪在跑!"); } } 工厂1: public class CarFactory { public static Car CreatCar(String type){ if("奥迪".equals(type)){ return new Audi(); }else if("比亚迪".equals(type)){ return new Byd(); }else { return null; } } } 工厂2: public class CarFactory2 { public static Car getAudi(){ return new Audi(); } public static Car getByd(){ return new Byd(); } } Client: /** * 测试在没有工厂模式的情况下 * @author Matrix42 * */ public class Client01 { public static void main(String[] args) { Car c1 = new Audi(); Car c2 = new Byd(); c1.run(); c2.run(); } } public class Client02 { public static void main(String[] args) { Car c1 = CarFactory.CreatCar("奥迪"); Car c2 = CarFactory.CreatCar("比亚迪"); c1.run(); c2.run(); } } 工厂方法模式 为了避免工厂模式的缺点,不完全满足OCP 工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式由一组实现了相同接口的工厂类 虽然工厂方法模式符号OCP但是会建很多类,实际用的比较多的还是简单工厂模式 Car接口: public interface Car { void run(); } Car的两个子类: public class Audi implements Car{ @Override public void run() { System.out.println("奥迪在跑!"); } } public class Byd implements Car{ @Override public void run() { System.out.println("比亚迪在跑!"); } } 两个工厂: public class AudiFactory implements CarFactory{ @Override public Car creatCar() { return new Audi(); } } public class BydFactory implements CarFactory{ @Override public Car creatCar() { return new Byd(); } } Client: public class C…

安装Storm集群
type: item
date: 2016-10-17T17:29:00+08:00
description: 软件版本 之前安装的zookeeper apache-storm-1.0.1 安装Storm 解压安装包 将bin目录加入到环境变量 配置storm.yaml storm.zookeeper.servers: - "192.168.112.139" - "192.168.112.140" - "192.168.112.142" storm.local.dir: "/home/matrix42/storm/apache-storm-1.0.1/data" storm.zookeeper.port: 2181 nimbus.seeds: ["master"] 注：每一个配置点前面需要加一个空格,否则启动时会报配置文件相关异常 拷贝文件到其余工作节点 scp -r storm 用户名@IP:地址 启动Storm 启动主控节点 storm nimbus 启动工作节点 storm supervisor 启动管理页面 在主控节点上运行storm ui 管理界面将运行在启动它的服务器的8080端口，日志文件在程序目录中logs文件夹下 后台运行的方法 nohup storm nimbus & 可以使用jps命令查看进程

搭建ZooKeeper集群
type: item
date: 2016-10-17T16:55:00+08:00
description: 环境 Centos 6.5 64位 jdk 1.8 u 101 python 2.7.12 zookeeper 3.4.8 https://www.python.org/ftp/python/2.7.12/下载tgz文件 修改服务器信息 更改master的hostname为master vim /etc/sysconfig/network更改hostname 重启后生效,用hostname命令检查是否生效 更改hosts文件 对应master和slave的ip vim /etc/hosts 配置免密码登录 使用```ssh-keygen命令生成密钥对 cp id_rsa.pub authorized_keys 把其他机器的公钥也复制到authorized_keys文件中 使用scp命令将hosts文件和authorized_keys文件传输到其他机器 spc 文件名 用户名@IP:地址 如果是文件夹加上`-r``` 使用ssh 主机名 尝试是否能连接到主机 安装jdk tar -zxvf 包名 把bin的路径添加到~/.bashrc文件中: PATH=$PATH:路径 export PATH 编译安装python 解压压缩包 进入目录 ./configure make 转到root,make install,再转回来 安装ZooKeeper 解压ZooKeeper 将zk的bin目录加入到环境变量中 复制conf中的zoo_sample.cfg为zoo.cfg 添加如下配置 dataDir=/home/matrix42/storm/zookeeper/data dataLogDir=/home/matrix42/storm/zookeeper/datalog clientPort=2181 server.1=master:2888:3888 server.2=slave1:2888:3888 server.3=slave2:2888:3888 新建data,datalog目录 在data目录下新建myid文件,按服务器写入1,2,3.... 配置说明 initLimit：多少个心跳时间内，允许其他server连接并初始化数据,如果ZooKeeper管理的数据较大,则应相应增大这个值 clientPort：服务的监听端口 dataDir：用于存放内存数据库快照的文件夹，同时用于集群的myid文件也存在这个文件夹里(注意：一个配置文件只能包含一个dataDir字样，即使它被注释掉了) dataLogDir：用于单独设置transaction log的目录,transaction log分离可以避免和普通log还有快照的竞争 syncLimit：多少个tickTime内,允许follower同步,如果follower落后太多，则会被丢弃 启动ZK集群 zkServer.sh start 如遇到Error contacting service. It is probably not running.错误可以把zk的端口号加入到iptables或关闭防火墙 可能需要安装nc包yum install nc zkServer.sh status检查ZK状态 zkServer.sh stop 停止ZK服务 zkServer.sh restart 重启ZK服务 Zookeeper常用命令

Maven
type: item
date: 2016-10-13T17:27:00+08:00
description: Maven能解决的问题 管理和构建项目 解决jar冲突的问题 解决依赖问题 Maven介绍及环境搭建 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具 下载地址:http://maven.apache.org/download.cgi 解压并配置环境变量 目录说明 bin:包含mvn的运行脚本 boot:包含一个类加载器的框架,maven使用它加载自己的类库 conf:配置文件目录,settings.xml lib:maven运行时用到的类库和第三方依赖类库 mvn -v 可以查看到maven的版本号,java版本,系统版本 maven项目的目录结构 src-->main-->java-->package src--test-->java-->package src--resources pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>test</groupId> <artifactId>test01</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>test01</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> 常用构建命令 编译项目:mvn compile 运行测试用例:mvn test 打包项目:mvn package 删除target文件夹(字节码文件和测试报告):mvn clean 将jar包安装到本地仓库:mvn install 自动创建目录骨架 archetype插件用于创建符合maven规定的目录骨架 创建目录骨架:mvn archety:generate 另一种方式:mvn archety:generate -DgroupId=com.lorinda.demo -DartifactId= mavenDemo -Dversion=1.0.0SNAPSHOT -Dpackage:com.lorinda.cc groupId一般为组织名,公司网址的反写+项目名 artifactId一般为项目名-模块名 version为版本号 代码所在包名 maven中的坐标和仓库 坐标:任何一个依赖,插件项目构件的输出,所有构件通过坐标作为其唯一标识 标识: <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> 仓库:用来管理依赖,如果在本地找不到依赖则到maven的全球的中央仓库找,并下载到本地 阿里云镜像仓库:http://maven.aliyun.com/nexus/content/groups/public 在maven的settings.xml 文件里配置mirrors的子节点,添加如下mirror: <mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror> http://maven.aliyun.com/nexus/#view-repositories;public~browsestorage 更改仓库默认位置 在settings.xml中加入:<localRepository>地址</localRe…

GOF23设计模式之:单例模式
type: item
date: 2016-10-13T11:53:00+08:00
description: 核心作用 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 常见应用场景 Windows的Task Manager(任务管理器)就是很典型的单例模式 Windows的Recycle Bin(回收站)也是典型的单例应用.在整个系统运行过程中,回收站一直维护着仅有的一个实例 项目中,读取配置文件的类,一般也只有一个对象.没有必要每次使用配置文件数据都new一个对象去读取 网站的计数器,一般也是采用单例模式实现,否则难以同步 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统 Application也是单例的典犁府用(Servlet中会涉及到) 在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理 在Servlet编程中,每个Servlet也是单例 在spring MVC架构/struts1框架中,控制器对象也是单例 单例模式的优点 由于单例模式只生产一个实例,减少了系统性能开销,当一个对象的生产需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存来解决 单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例,负责所有数据表的映射处理 常见的五种单例模式实现方式 主要 饿汉式(线程安全,调用效率高,但是不能延时加载) 懒汉式(线程安全,调用效率不高,但是可以延时加载) 其他 双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用) 静态内部类式(线程安全,调用效率高,可以延时加载) 枚举单例(线程安全,调用效率高,不能延时加载) 如何选用 单例对象 占用资源少 不需要延时加载 枚举式 好于 饿汉式 单例对象 占用资源多 需要延时加载 静态内部类 好于 懒汉式 饿汉式实现(单例对象立即加载) /** * 饿汉式 * @author Matrix42 * */ public class SingletonDemo01 { //类初始化时立即加载 private static SingletonDemo01 instance = new SingletonDemo01(); private SingletonDemo01(){ } //方法没有同步,调用效率高 public static SingletonDemo01 getInstance(){ return instance; } } 饿汉式单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问该对象的问题.虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题.因此,可以省略synchronized关键字 问题:如果只加载本类,而不调用getInstance(),甚至永远没有调用,则会造成资源浪费! 懒汉式实现(单例对象延迟加载) public class LazayLoad { private static LazayLoad instance; private LazayLoad(){ } public static synchronized LazayLoad getInstance(){ if (instance==null) { instance = new LazayLoad(); } return instance; } } 问题:资源利用率高了,但是每次调用getInstance()方法都要同步,并发效率低了 双重检测锁实现 这个模式将同步内容放到if内部,提高了执行的效率,不比每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了 由于JVM底层内部模型原因,偶尔会出现问题,不建议使用 public class SingletonDemo3 { private static SingletonDemo3 instance = null; public static SingletonDemo3 getInstance() { if (instance == null) { SingletonDemo3 sc; synchronized (SingletonDemo3.class) { sc = instance; if (sc == null) { synchronized (SingletonDemo3.class) { if(sc == null) { sc = new SingletonDemo3(); } } instance = sc; } } } …

设计模式GOF23
type: item
date: 2016-10-13T11:45:00+08:00
description: 将设计者的思维融入学习和工作中 设计模式分类 创建型模式 单例模式 工厂模式 抽象工厂模式 建造者模式 原型模式 关注对象的创建过程 结构模型 设配器模式 桥接模式 装饰模式 组合模式 外观模式 亨元模式 代理模式 关注对象和类的组织 行为模式 模板方法模式 命令模式 迭代器模式 观察者模式 中介模式 备忘录模式 解释器模式 状态模式 策略模式 职责链模式 访问模者式 关注系统中对象之间的相互交互,研究系统在运行时对象之间的相互通信和写作,进一步明确对象的职责

Java 网络编程
type: item
date: 2016-10-12T15:07:00+08:00
description: 基本概念 什么是计算机网络 把分布在不同地理区域的计算机与专门的外部设备用通信线路互联成一个规模大,功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件,软件,数据信息等资源 计算机网络的主要功能 资源共享 信息传递与集中处理 均衡负荷与分布处理 综合信息服务(www/综合业务数字网络ISDN) 什么是网络通信协议 计算机网络中实现通信必须有一些约定即通信协议,对速率,传输代码,代码结构,传输控制步骤,出错控制等制定标准 网络通信接口 为了使两个节点之间能进行对话,必须在他们之间建立通信工具(即接口),彼此之间能进行信息交换.接口包括两部分: 硬件装置:实现节点之间的信息传送 软件装置:规定双方进行通信的约定协议 网络分层 原因 由于节点之间联系很复杂,在制定协议时,把复杂成分分解成一些简单的成分,再将它们复合起来.最常用的复合方式是层次方式,即同层间可以通信,上一层可以调用下一次,而与再下一层不发生关系 通信协议的分层 OSI参考模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 TCP/IP参考模型 应用层 传输层(TCP/UDP) 网络层(IP) 物理+数据链路层 传输协议 TCP(transfer control prottocol) 一种面向连接(连接导向)的,可靠的,基于字节流的运输层(Transport layer)通信协议 特点 面向连接 点到点的通信 高可靠性 TCP三次握手(Three-way Handshake) UDP(User Datagram Protocol) 一种无连接的传输层协议,提供面向事物的简单不可靠信息传送服务 特点 非面向连接 传输不可靠 数据可能丢失 数据封装拆分 网络编程值地址及端口 1.InetAddress :封装 IP 及DNS 方法: getHostAddress() 返回ip地址 getHostName() 返回域名|本机为计算机名 InetAddress.getLocalHost(); InetAddress.getByName("ip地址|域名"); 2.InetSocketAddress:封装端口 1)创建对象: InetSocketAddress(String hostname, int port) InetSocketAddress(InetAddress addr, int port) 2)方法： getAddress() getHostName() getPort() public class InetDemo01 { /** * @param args * @throws UnknownHostException * @throws MalformedURLException */ public static void main(String[] args) throws UnknownHostException{ //使用getLocalHost方法创建InetAddress对象 InetAddress addr = InetAddress.getLocalHost(); System.out.println(addr.getHostAddress()); //返回：192.168.1.100 System.out.println(addr.getHostName()); //输出计算机名 //根据域名得到InetAddress对象 addr = InetAddress.getByName("www.163.com"); System.out.println(addr.getHostAddress()); //返回 163服务器的ip:61.135.253.15 System.out.println(addr.getHostName()); //输出：www.163.com //根据ip得到InetAddress对象 addr = InetAddress.getByName("61.135.253.15"); System.out.println(addr.getHostAddress()); //返回 163服务器的ip:61.135.253.15 System.out.println(addr.getHostName()); //输出ip而不是域名。如果这个IP地 址不存在或DNS服务器不允许进行IP地址和域名的映射，getHostName方法就直接返回这个IP地址。 } } import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; /** * 封装端口:在InetAddres…

Java 其他流
type: item
date: 2016-10-11T16:12:00+08:00
description: 节点流 字节数组节点流 输入流:ByteArrayInputStream read(byte[] b,int off,int len) close() 不用关闭 输出流:ByteArrayOutputStream write(byte[] b,int off,int len) toByteArray() import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; public class Demo08 { public static void main(String[] args) throws IOException { read(write()); } public static void read(byte[] src) throws IOException { //选择流 InputStream is = new BufferedInputStream(new ByteArrayInputStream(src)); //操作 byte[] flush = new byte[1024]; int len = 0; while(-1!=(is.read(flush))){ System.out.println(new String(flush)); } } public static byte[] write(){ //目的地 byte[] dest; //选择流 ByteArrayOutputStream bos = new ByteArrayOutputStream(); //操作写出 String msg = "操作与文件输入流一致"; byte[] info = msg.getBytes(); bos.write(info,0,info.length); //获取数据 dest = bos.toByteArray(); return dest; } } import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** *1、文件 --程序->字节数组 *1)、文件输入流 * 字节数组输出流 * * * 2、字节数组 --程序->文件 * 1)、字节数组输入流 * 文件输出流 * @author Administrator * */ public class ByteArrayDemo02 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { byte[] data =getBytesFromFile("e:/xp/test/1.jpg"); toFileFromByteArray(data,"e:/xp/test/arr.jpg"); } /** * 2、字节数组 --程序->文件 */ public static void toFileFromByteArray(byte[] src,String destPath) throws IOException{ //创建源 //目的地 File dest=new File(destPath); //选择流 //字节数组输入流 InputStream is =new BufferedInputStream(new ByteArrayInputStream(src)); //文件输出流 OutputStream os =new BufferedOutputStream(new FileOutputStream(dest)); //操作 不断读取字节数组 byte[] flush =new byte[1]; int len =0; while(-1!=(len =is.read(fl…