跟晓明一起学java之java设计模式
一、设计模式的分类
1、创建型模式
有五种:工厂方法模式,抽象工厂模式,单例模式,创建者模式,原型模式。
2、结构型模式
有七种:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
3、行为型模式
有十一种:策略模式,模板方法模式,责任链模式,命令模式,迭代子模式,观察者模式,备忘录模式,状态模式,
中介者模式,访问者模式,解释器模式。
二、设计模式的基本原则
三、设计模式详解
1、创建型模式
简单工厂模式
public interface ISend {
public void send();
}
/**
* 邮件发送实现类
* @author Administrator
*
*/
public class MailSend implements ISend{
@Override
public void send() {
System.out.println("邮件发送信息!");
}
}
/**
*短信发送实现类
* @author Administrator
*
*/
public class MessageSend implements ISend{
@Override
public void send() {
System.out.println("短信发送信息!");
}
}
/**
* 简单工程类
* @author Administrator
*
*/
public class SigleMethodFactory {
public ISend produce(String type){
if("mail".equals(type)){
return new MailSend();
}else if("message".equals(type)){
return new MessageSend();
}
return null;
}
}
<5>测试
public class SimpleFactoryTest {
public static void main(String[] args){
ISend send = new SigleMethodFactory().produce("mail");
send.send();
}
}
输出:邮件发送信息!
public class MutiMethodSimpleFatory {
public ISend produceMessage(){
return new MessageSend();
}
public ISend produceMail(){
return new MailSend();
}
}
<4>测试
public class MutilMethodSmpFactoryTest {
public static void main(String[] args) {
ISend send = new MutiMethodSimpleFatory().produceMessage();
send.send();
}
}
输出:短信发送信息!
1.1 工厂方法模式(Factory Method)
public interface IFactoryMethod {
public ISend produce();
}
<4>创建工厂类实现类
public class MailFatory implements IFactoryMethod{
@Override
public ISend produce(){
return new MailSend();
}
}
public class MessageFacory implements IFactoryMethod {
@Override
public ISend produce() {
return new MessageSend();
}
}
<5>测试
public class FactoryMethodTest {
public static void main(String[] args){
IFactoryMethod factory = new MailFatory();
ISend send = factory.produce();
send.send();
}
}
输出:短信发送信息!
1.2 抽象工厂模式(Abstact Factory)
工厂方法与抽象工厂的区别:
工厂方法模式:
一个抽象产品类,可以派生出多个具体的产品类。
一个抽象工厂类,可以派生出多个具体的工厂类。
抽象工厂模式:
多个抽象产品类,每个抽象产品都可以派生出多个具体的实现类。
一个抽象工厂类,可以派生出多个具体的工厂类。
区别:
工厂方法只有一个抽象产品,抽象工厂有多个。
工厂方法的具体实现类只能创建一个类的实例,而抽象工厂可以创建多个。
工厂方法侧重于怎么创建,抽象工厂侧重于创建那些。
比如利用抽象工厂实现对数据库访问的不同实现(jdbc,hibernate)等。
<1>关系图
<2>工厂接口类
public interface IAbstractFactory {
public IMouse createMouse();
public IKeyBoard createKeyBoard();
}
<3>工厂接口的实现类
public class IntellFactory implements IAbstractFactory{
@Override
public IMouse createMouse() {
return new IntellMouse();
}
@Override
public IKeyBoard createKeyBoard() {
return new IntellKeyBoard();
}
}
public class LenevoFactory implements IAbstractFactory {
@Override
public IMouse createMouse() {
return new LenevoMouse();
}
@Override
public IKeyBoard createKeyBoard() {
return new LenevoKeyBoard();
}
}
<4>实体类接口
public interface IMouse {
public void click();
}
public interface IKeyBoard {
public void hit();
}
<5>实体类接口实现类
public class LenevoMouse implements IMouse{
@Override
public void click() {
System.out.println("lenevo mouse");
}
}
public class IntellMouse implements IMouse{
@Override
public void click() {
System.out.println("intell mouse");
}
}
public class LenevoKeyBoard implements IKeyBoard{
@Override
public void hit() {
System.out.println("lenevo keyBoard");
}
}
public class IntellKeyBoard implements IKeyBoard {
@Override
public void hit() {
System.out.println("intell keyBoard");
}
}
<5>测试
public class AbstractFatoryTest {
public static void main(String[] args) {
IAbstractFactory factory = new IntellFactory();
IKeyBoard keyBoard = factory.createKeyBoard();
IMouse mouse = factory.createMouse();
keyBoard.hit();
mouse.click();
}
}
输出:
intell keyBoard
intell mouse
1.3 单例模式(Sigleton)
单例模式的特点:
单例类必须只有一个实例;
单例类必须自己创建自己的实例;
单例类必须给其他所有实例提供这一个对象。
单例模式就是要保证某个类只有一个实例,并且自行实例化并向系统提供这个实例。在计算及系统中,线程池,日志,
缓存,打印机等常被设计成单例类。
<1>懒汉式单例
/**
* 线程不安全的
* @author Administrator
*
*/
public class LazySingleton {
//私有的静态变量,防止被引用
private static LazySingleton instance = null;
//私有的构造器,防止被实例化
private LazySingleton(){
}
private static LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}
/**
* 线程安全的懒汉式
* @author Administrator
*
*/
public class SafeLazySingleton {
private static SafeLazySingleton instance = null;
private static synchronized SafeLazySingleton init(){
if(instance == null){
return new SafeLazySingleton();
}
return instance;
}
public static SafeLazySingleton getInstance(){
if(instance == null){
init();
}
return instance;
}
}
<2>饿汉式单例
public class HungrySingle {
private static HungrySingle instance = new HungrySingle();
private HungrySingle(){
}
public static HungrySingle getInstance(){
return instance;
}
}
1.4 建造者模式(Builder)
工厂模式提供的是创建单个类的模式,建造者模式将多个产品集中起来进行管理,用来创建集合对象。public class Builder {
public List<ISend> list = new ArrayList<ISend>();
public void produceMailSend(int count){
for(int i = 0;i < count;i++){
list.add(new MailSend());
}
}
public void produceMessageSend(int count){
for(int i = 0;i < count;i++){
list.add(new MessageSend());
}
}
}
从这点可以看出,创建者模式是将很多功能集成到一个类里,这个类可以创造出比较复杂的东西。
1.5 原型模式(ProtoType)
原形模式,就是讲一个对象作为原型,对其进行复制,克隆,产生一个与原来对象相类似的新对象。
一个原型类只需要实现cloneable接口,覆盖clone方法(),super.clone()调用object的clone方法完成复制。
浅复制:将一个对象复制后,基本类型的变量会被重新创建,而引用类型,指向的还是原对象所指向的。
深复制:无论基本类型的变量还是引用类型的变量,都会重新的创建一份。
public class ProtoType implements Cloneable{
//浅复制
public Object clone() throws CloneNotSupportedException{
ProtoType proto = (ProtoType)super.clone();
return proto;
}
//深复制
public Object deepClone() throws IOException, ClassNotFoundException{
//写入当前对象的二进制流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//读出二进制流产生的新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
所以说,深复制需要采用流的方式读入当前对象的二进制输入,然后在写出二进制数据到新的对象。
2、结构型模式
2.1 适配器模式(Adapter)
2.1.1 类的适配器
public class Source {
public void method1(){
System.out.println("Source method1");
}
}
<3>目标接口
public interface ITarget {
public void method1();
public void method2();
}
<4>类适配器
public class ClassAdapter extends Source implements ITarget{
@Override
public void method2() {
System.out.println("ClassAdapter method2");
}
}
<5>测试
public class ClassAdapterTest {
public static void main(String[] args){
ITarget target = new ClassAdapter();
target.method1();
target.method2();
}
}
输出:
ClassAdapter method2
2.1.2 对象的适配器
public class ObjectAdapter implements ITarget{
Source source = null;
public ObjectAdapter(Source source){
this.source = source;
}
@Override
public void method1() {
source.method1();
}
@Override
public void method2() {
System.out.println("ObjectAdapter method2");
}
}
2.1.3 接口适配器模式
有些时候,我们写一个接口,里面会有多个抽象方法,当我们写接口的实现类的时候,必须要实现这个接口的所有方法,这明显比较浪费,public abstract class InterfaceAdapter implements ITarget{
@Override
public void method1() {
}
@Override
public void method2() {
}
}
<3>具体实现类
public class Sub1 extends InterfaceAdapter{
@Override
public void method1() {
System.out.println("Sub1 method1");
}
}
public class Sub2 extends InterfaceAdapter {
@Override
public void method2() {
System.out.println("Sub2 method2");
}
}
总结:
接口适配器:当不希望实现一个接口的所有方法时,可以创建一个抽象类,实现所有方法,我们写别的类时,直接继承抽象类即可。
2.2装饰器模式(Decorator)
public interface DecoraterInterface {
public void method1();
}
<3>被装饰类
public class Source implements DecoraterInterface {
@Override
public void method1() {
System.out.println("Source method1");
}
}
<4>装饰类
public class Decorator implements DecoraterInterface{
Source source = null;
public Decorator(Source source){
this.source = source;
}
@Override
public void method1() {
System.out.println("前装饰");
source.method1();
System.out.println("后装饰");
}
}
装饰器的应用场景:
2.3 代理模式
public interface IProxyInterface {
public void method();
}
<3>被代理类
public class Source implements DecoraterInterface {
@Override
public void method1() {
System.out.println("Source method1");
}
}
<4>代理类
public class Proxy implements IProxyInterface{
Source source = null;
public Proxy(){
source = new Source();
}
@Override
public void method() {
System.out.println("代理前");
source.method();
System.out.println("代理后");
}
}
<5>测试类
public class ProxyTest {
public static void main(String[] args) {
IProxyInterface proxy = new Proxy();
proxy.method();
}
}
输出:
Source method!
代理后
2.4 外观模式(Facade)
public class Cpu {
public void start(){
System.out.println("Cpu start");
}
public void shutdown(){
System.out.println("cpu shutdown");
}
}
public class Memory {
public void start(){
System.out.println("Memory start");
}
public void shutdown(){
System.out.println("Memory shutdown");
}
}
<3>外观类
public class ComputerFacade {
private Memory memory = null;
private Cpu cpu = null;
public ComputerFacade(){
memory = new Memory();
cpu = new Cpu();
}
public void startup(){
memory.start();
cpu.start();
}
public void shutdown(){
memory.shutdown();
memory.shutdown();
}
}<strong>
</strong>
<4>测试类
public class FacadeTest {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.startup();
computer.shutdown();
}
}
输出:
Cpu start
Memory shutdown
Memory shutdown
总结:如果没有ComputerFacade类,则Memory与Cpu类则相互依赖,修改一个类,就会导致另外类的修改。
2.5 桥接模式(Bridge)
public interface SourceAble {
public void method();
}
<3>定义实现类
public class Sub1 implements SourceAble {
@Override
public void method() {
System.out.println("Sub1 method!");
}
}
public class Sub2 implements SourceAble {
@Override
public void method() {
System.out.println("Sub2 method!");
}
}
public abstract class Bridge {
SourceAble source = null;
public void method(){
source.method();
}
public SourceAble getSource() {
return source;
}
public void setSource(SourceAble source) {
this.source = source;
}
}
public class MyBridge extends Bridge {
public void method(){
getSource().method();
}
}
<5>测试类
public class BridgeTest {
public static void main(String[] args) {
SourceAble source = new Sub1();
Bridge bridge = new MyBridge();
bridge.setSource(source);
bridge.method();
}
}
输出:
2.6 组合模式(Composite)
public class TreeNode {
private String name;
private TreeNode parent;
private Vector<TreeNode> children = new Vector<TreeNode>();
public TreeNode(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
//添加孩子节点
public void add(TreeNode node){
children.add(node);
}
//删除孩子节点
public void remove(TreeNode node){
children.remove(node);
}
//取得孩子节点
public Enumeration<TreeNode> getChildren(){
return children.elements();
}
}
public class Tree {
TreeNode root = null;
public Tree(String name) {
root = new TreeNode(name);
}
public static void main(String[] args) {
Tree tree = new Tree("A");
TreeNode nodeB = new TreeNode("B");
TreeNode nodeC = new TreeNode("C");
nodeB.add(nodeC);
tree.root.add(nodeB);
System.out.println("build the tree finished!");
}
}
使用场景:将多个对象组合在一起进行操作,常用于表示树结构,录入二叉树等。
2.7 享元模式(Flyweight)
public class ConnectionPool {
private Vector<Connection> pool;
/*公有属性*/
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
private int poolSize = 100;
private static ConnectionPool instance = null;
Connection conn = null;
/*构造方法,做一些初始化工作*/
private ConnectionPool() {
pool = new Vector<Connection>(poolSize);
for (int i = 0; i < poolSize; i++) {
try {
Class.forName(driverClassName);
conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/* 返回连接到连接池 */
public synchronized void release() {
pool.add(conn);
}
/* 返回连接池中的一个数据库连接 */
public synchronized Connection getConnection() {
if (pool.size() > 0) {
Connection conn = pool.get(0);
pool.remove(conn);
return conn;
} else {
return null;
}
}
}<strong> </strong>
通过连接池的管理,实现了数据库链接的共享,不需要每一次都从新链接,节省了数据库重新创建的开销,提升了系统的性能。
3.行为型模式
第一类:父类与子类 策略模式,模板方法模式3.1 策略模式
3.2 模板方法模式(Template method)
3.3观察者模式
3.5 责任链模式(Chain of Responsibility)
3.6 命令模式(Commond)
3.7 备忘录模式
3.8 状态模式
3.9 中介者模式
3.10 访问者模式
3.11 解释器模式