设计模式-创建模式
2016-03-19 19:31
357 查看
设计模式分为:创建模式、结构模式、行为模式
优点:
1. 良好的封装性,代码结构清晰。要创建一个产品只需要知道产品类的名字,不需要了解产品类的具体实现。
2. 良好的扩展性。要添加一个新的产品,只需要继承抽象产品类就可以了。
3. 屏蔽了产品类。将产品的具体实现与调用者本身隔离起来。
应用场景:
1. 工厂方法模式是“new”的替代品,在使用到“new”的时候都可以用,但要避免代码的复杂度,不要过度使用。
2. 需要有灵活的可扩展框架时,可以考虑采用工厂方法模式。
3. 工厂方法模式可以用在异构项目中。
4. 可以使用在测试驱动开发的框架下。
优点:
1. 封装性.每个个产品的使用者不需要关心产品的具体实现.
2. 产品内部的约束为非公开的.产品组内的约束关系是在工厂内部实现的.
3. 当要添加一个产品等级时,是比较方便的,只需要添加一个继承于抽象工厂的工厂类就可以了.
缺点:
产品组的扩展性很困难,需要在抽象工厂中添加一个新的方法,而导致所有的工厂类都需要重新写.
应用场景:
当有一组具有相同约束的产品或者对象时,这些对象的创建可以使用抽象工厂模式.
优点:
1. 实例控制.单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
2. 灵活性.因为类控制了实例化过程,所以类可以灵活更改实例化过程.
3. 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能.
缺点:
1. 开销.虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
2. 可能的开发混淆.使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
3. 单例类的扩展困难。
4. 单例类的职责过重,在一定程度上违背了“单一职责原则”
应用场景:
1. 需要产生唯一实例的场景.
2. 创建实例需要消耗的资源较多,如访问IO和数据库等.
3. 需要定义大量的静态常量或者静态方法等(当然,直接声明为static也可以).
优点:
1. 良好的性能.使用clone方法,进行二进制流的拷贝比是用new方法性能要好的多,特别是在一个大量循环的内部.
2. 规避了构造函数的约束.直接进行内存拷贝,不执行构造函数,既是优点又是缺点.
应用场景:
1. 资源优化场景.类初始化需要消耗很多资源的情况下,包括数据,硬件资源等.
2. 性能和安全要求的场景.通过new产生一个对象需要非常繁琐的数据准备或者访问权限的场景.
3. 一个对象,多个修改者的场景.一个对象需要被多个修改者进行修改的场景.
优点:
1. 封装性;使对象的使用者不必知道对象的实现.
2. 良好的扩展性;建造者是相互独立的,可以很方便地进行扩展.
3. 便于控制细节风险;由于建造是相互独立的,因此可以将建造者逐步细化,而不对其他模块产生影响.
缺点:
由于不同的建造者之间是其创建步骤不同而产生的,每个建造者都把产品的创建步骤进行封装,就导致无法满足分步创建的要求.
应用场景:
1. 相同的方法,不同的顺序或者步骤,产生不同的结果.
2. 多个部件或者零件可以装配到同一个对象中,而不同的装配步骤会产生不同的对象.
3. 产品具有比较复杂的内部结构,不同的顺序就会产生不同的产品
4. 产品的创建需要调用其他的对象,而这些对象在产品的创建过程中又不容易获得.
创建模式:
(1)Factory-工厂模式
定义:定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。由产品类的具体类来决定,将要实例化哪一个产品类。优点:
1. 良好的封装性,代码结构清晰。要创建一个产品只需要知道产品类的名字,不需要了解产品类的具体实现。
2. 良好的扩展性。要添加一个新的产品,只需要继承抽象产品类就可以了。
3. 屏蔽了产品类。将产品的具体实现与调用者本身隔离起来。
应用场景:
1. 工厂方法模式是“new”的替代品,在使用到“new”的时候都可以用,但要避免代码的复杂度,不要过度使用。
2. 需要有灵活的可扩展框架时,可以考虑采用工厂方法模式。
3. 工厂方法模式可以用在异构项目中。
4. 可以使用在测试驱动开发的框架下。
/** 简单工厂*/ public interface Car { public void getName(); public class Bmw implements Car { public void getName() { System.out.println("My name is Bmw !"); } } public class Benz implements Car { public void getName() { System.out.println("My name is Benz !"); } } public class CarFactory { public static Car produceCar(String carName) { if (carName.equalsIgnoreCase("Bmw")) { return new Bmw(); } else if (carName.equalsIgnoreCase("Benz")) { return new Benz(); } else throw new Exception(); } }
/** 工厂方法*/ public abstract class Person { boolean gender; public abstract String say(); } public class Male extends Person{ public Male(){ gender=true; } @Override public String say() { return "I'm a man, I'm strong!"; } } public class Female extends Person{ public Female(){ this.gender=false; } @Override public String say() { return "I'm a girl, I'm thin!"; } } public class PersonFactory { public static Person getPerson(Class c){ Person person = null; try { person = (Person) Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return person; } public static void main(String[] args){ Person person = PersonFactory.getPerson(Male.class); System.out.println(person.say());//I'm a man, I'm strong! person = PersonFactory.getPerson(Female.class); System.out.println(person.say());//I'm a man, I'm strong! } }
(2)抽象工厂
定义:为创建一组相关或者相互依赖的对象提供一个接口.优点:
1. 封装性.每个个产品的使用者不需要关心产品的具体实现.
2. 产品内部的约束为非公开的.产品组内的约束关系是在工厂内部实现的.
3. 当要添加一个产品等级时,是比较方便的,只需要添加一个继承于抽象工厂的工厂类就可以了.
缺点:
产品组的扩展性很困难,需要在抽象工厂中添加一个新的方法,而导致所有的工厂类都需要重新写.
应用场景:
当有一组具有相同约束的产品或者对象时,这些对象的创建可以使用抽象工厂模式.
// 抽象工厂 public abstract class VehicleFactory { public abstract Moveable produce(); } // 抽象产品 public interface Moveable { public void run(); } // 具体的产品对象 public class Plane implements Moveable{ public void run() { System.out.println("I'm plane, I can fly..."); } } public class Boat implements Moveable { public void run() { System.out.println("I'm boat, I can swim..."); } } public class Tank implements Moveable { public void run() { System.out.println("I'm tank, I can run..."); } } // 具体的产品工厂 public class PlaneFactory extends VehicleFactory{ @Override public Moveable produce() { return new Plane(); } } public class BoatFactory extends VehicleFactory{ @Override public Moveable produce() { return new Boat(); } } public class TankFactory extends VehicleFactory{ @Override public Moveable produce() { return new Tank(); } } // 测试 public static void main(String[] args){ VehicleFactory vf = null; Moveable vehicle = null; vf = new PlaneFactory(); vf = new TankFactory(); vf = new BoatFactory(); vehicle = vf.produce(); vehicle.run(); }
(3)Singleton-单例模式
定义:确保一个类只有一个实例,并且自行实例化,向整个系统提供该类的实例.优点:
1. 实例控制.单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
2. 灵活性.因为类控制了实例化过程,所以类可以灵活更改实例化过程.
3. 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能.
缺点:
1. 开销.虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
2. 可能的开发混淆.使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
3. 单例类的扩展困难。
4. 单例类的职责过重,在一定程度上违背了“单一职责原则”
应用场景:
1. 需要产生唯一实例的场景.
2. 创建实例需要消耗的资源较多,如访问IO和数据库等.
3. 需要定义大量的静态常量或者静态方法等(当然,直接声明为static也可以).
//饿汉模式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } } //懒汉模式 public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } } /* * 懒汉模式 * synchronized 加锁,保证线程安全 * 每一次都要进入同步区,进行判断空,效率低下 * */ public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } return instance; } } /* * 懒汉模式 * synchronized 加锁,保证线程安全 * 与上面一种方式相比,只会进入同步区一次,效率高 * */ public class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } } /* * 懒汉模式 * 静态内部类,内部类的加载时线程安全的 * */ public class Singleton { private Singleton(){} private static final class InnerClass{ static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return InnerClass.instance; } }
(4)Prototype-原型模式
定义:使用原型实例来规定要创建的对象的种类,并通过拷贝这些原型来创建新的对象.优点:
1. 良好的性能.使用clone方法,进行二进制流的拷贝比是用new方法性能要好的多,特别是在一个大量循环的内部.
2. 规避了构造函数的约束.直接进行内存拷贝,不执行构造函数,既是优点又是缺点.
应用场景:
1. 资源优化场景.类初始化需要消耗很多资源的情况下,包括数据,硬件资源等.
2. 性能和安全要求的场景.通过new产生一个对象需要非常繁琐的数据准备或者访问权限的场景.
3. 一个对象,多个修改者的场景.一个对象需要被多个修改者进行修改的场景.
public interface Prototype { Prototype clone(); } public class Email implements Prototype{ public Prototype clone(){ return new Email(); } } public class Mail implements Cloneable, Serializable{ public Mail clone(){ Mail mail = null; try { mail = (Mail) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return mail; } public Mail deepClone() throws IOException{ try { ObjectOutputStream oos; ObjectInputStream ois; ByteArrayOutputStream baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(this); ByteArrayInputStream bais = new ByteArrayInputStream(baos .toByteArray()); ois = new ObjectInputStream(bais); return (Mail) ois.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } } // 测试 public static void main(String[] args){ Mail mail = new Mail(); Mail mail1 = mail.clone(); Mail mail2 = null; try { mail2 = mail.deepClone(); } catch (IOException e) { e.printStackTrace(); } Prototype email = new Email(); Prototype email1 = email.clone(); System.out.println(mail.getClass().getName() + mail.getClass()); System.out.println(mail1.getClass().getName() + mail1.getClass()); }
(5)Builder-建造者模式
定义:将一个复杂对象的创建与其表示相分离,使得经过同样的创建过程而可以得到不同的表示.优点:
1. 封装性;使对象的使用者不必知道对象的实现.
2. 良好的扩展性;建造者是相互独立的,可以很方便地进行扩展.
3. 便于控制细节风险;由于建造是相互独立的,因此可以将建造者逐步细化,而不对其他模块产生影响.
缺点:
由于不同的建造者之间是其创建步骤不同而产生的,每个建造者都把产品的创建步骤进行封装,就导致无法满足分步创建的要求.
应用场景:
1. 相同的方法,不同的顺序或者步骤,产生不同的结果.
2. 多个部件或者零件可以装配到同一个对象中,而不同的装配步骤会产生不同的对象.
3. 产品具有比较复杂的内部结构,不同的顺序就会产生不同的产品
4. 产品的创建需要调用其他的对象,而这些对象在产品的创建过程中又不容易获得.
public class Car { private String wheel; private String engine; private String plateNumber; public String toString(){ return "plateNumber:"+plateNumber+"\nwheel:"+wheel+"\nengine:"+engine; } } public interface Builder { public Car produceCar(); public void setIngredient(); } public class BenzBuilder implements Builder { Car benz = new Car(); public Car produceCar() { return benz; } public void setIngredient() { benz.setWheel("benz.Wheel"); benz.setEngine("benz.Engine"); benz.setPlateNumber("benz.67890"); } } public class BmwBuilder implements Builder { Car bmwCar = new Car(); public Car produceCar() { return bmwCar; } public void setIngredient() { bmwCar.setWheel("bmw.Wheel"); bmwCar.setEngine("bmw.Engine"); bmwCar.setPlateNumber("bmw.12345"); } } // 测试 public static void main(String[] args){ Builder builder = null; builder = new BmwBuilder(); builder = new BenzBuilder(); builder.setIngredient(); String carInfo = builder.produceCar().toString(); System.out.println(carInfo); }
相关文章推荐
- 多线程的解释
- 第三周作业
- 四则运算
- poj 2528 数的离散化+线段树
- php生命周期
- JS中最常用的55个技巧
- cannot resolve symbol r AndroidStudio R文件丢失
- 使用EasyBCD安装Win7和Ubuntu双系统
- 对一个程序的分析
- iOS之07-三大特性之多态 + NSString类
- 机电传动控制4
- C#编程之神奇程序找数
- NBUT - 1647 又一道简单题 (暴力模拟)
- 使用jQuery的文件上传插件Uploadify完成html的表单提交
- js实现找质因数
- HDU 4324 Triangle LOVE(拓扑排序)
- 蓝桥杯 剪格子
- 非对称加密和对称加密的区别
- 初识Android
- JavaWeb开发之四:servlet技术