1,简单工厂
1.1 简单工厂说明
1.2 代码示例
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
/**
* @author Rollen-Holt 设计模式之 简单工厂模式
*/
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
// 构造工厂类
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}
2,工厂反射
2.1 代码示例
/**
* @author Rollen-Holt 设计模式之 反射工厂模式
*/
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
// 构造工厂类
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory{
public static fruit getInstance(String fruitName)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
// 这边使用的是Java的Reflection机制来产生实例
return (fruit)Class.forName(fruitName).newInstance();
}
}
class hello{
public static void main(String[] a){
fruit f= Factory.getInstance(Apple.class.getName());
f.eat();
}
}
构造函数有参数的情况:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
abstract class fruit {
protected String person;
protected int number;
protected String emotion;
// 构造函数有三个参数
public fruit(String person, int number, String emotion) {
super();
this.person = person;
this.number = number;
this.emotion = emotion;
}
public abstract void eat();
}
class Apple extends fruit {
public Apple(String person, int number, String emotion) {
super(person, number, emotion);
// TODO Auto-generated constructor stub
}
public void eat() {
String sentence = this.person + " ate " + this.number + " apples "
+ this.emotion;
System.out.println(sentence);
}
}
class Orange extends fruit {
public Orange(String person, int number, String emotion) {
super(person, number, emotion);
// TODO Auto-generated constructor stub
}
public void eat() {
String sentence = this.person + " ate " + this.number + " oranges "
+ this.emotion;
System.out.println(sentence);
}
}
// 构造工厂类
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory {
public static fruit getInstance(String fruitName, String person,
int number, String emotion) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SecurityException,
NoSuchMethodException, IllegalArgumentException,
InvocationTargetException {
//这边使用的是Java的Reflection机制来产生实例
Class fruitClass = Class.forName(fruitName);
//用来获取构造函数
Class[] argsClass = new Class[3];
argsClass[0] = String.class;
argsClass[1] = int.class;
argsClass[2] = String.class;
Constructor cons = fruitClass.getConstructor(argsClass);
//用来获取实例对象
Object[] objs = new Object[3];
objs[0] = person;
objs[1] = number;
objs[2] = emotion;
return (fruit) cons.newInstance(objs);
}
}
class test2 {
public static void main(String[] a) throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SecurityException,
NoSuchMethodException, IllegalArgumentException,
InvocationTargetException {
fruit f = Factory.getInstance(Apple.class.getName(), "Tom", 3,
"happily");
f.eat();
}
}
3,抽象工厂
3.1 抽象工厂模式
为了方便引进抽象工厂模式,引进一个新概念:产品族(Product Family)。所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族。如图:
图中一共有四个产品族,分布于三个不同的产品等级结构中。只要指明一个产品所处的产品族以及它所属的等级结构,就可以唯一的确定这个产品。
所谓的抽象工厂是指一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。如果用图来描述的话,如下图:
3.2 抽象工厂模式的结构
图中描述的东西用产品族描述如下:
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。
3.3 程序举例
所以如下展示了2X3种实例的产生方式(2种水果[苹果,橘子];3种产地[北方,南方,温室])
//Fruit.java
public interface Fruit {
public void get();
}
// Apple.java
public abstract class Apple implements Fruit {
public abstract void get();
}
// SouthApple.java
public class SouthApple extends Apple {
@Override
public void get() {
System.out.println("采集南方苹果");
}
}
// NorthApple.java
public class NorthApple extends Apple {
@Override
public void get() {
System.out.println("采集北方苹果");
}
}
// WenshiApple.java
public class WenshiApple extends Apple {
@Override
public void get() {
System.out.println("采集温室苹果");
}
}
// Banana.java
public abstract class Banana implements Fruit {
public abstract void get();
}
// NorthBanana.java
public class NorthBanana extends Banana {
@Override
public void get() {
System.out.println("采集北方香蕉");
}
}
// SouthBanana.java
public class SouthBanana extends Banana {
@Override
public void get() {
System.out.println("采集南方香蕉");
}
}
// WenshiBanana.java
public class WenshiBanana extends Banana {
@Override
public void get() {
System.out.println("采集温室香蕉");
}
}
// FruitFactory.java
public interface FruitFactory {
// 实例化Apple
public Fruit getApple();
// 实例化Banana
public Fruit getBanana();
}
// NorthFruitFactory.java
public class NorthFruitFactory implements FruitFactory {
public Fruit getApple() {
return new NorthApple();
}
public Fruit getBanana() {
return new NorthBanana();
}
}
// SouthFruitFactory.java
public class SouthFruitFactory implements FruitFactory {
public Fruit getApple() {
return new SouthApple();
}
public Fruit getBanana() {
return new SouthBanana();
}
}
// WenshiFruitFactory.java
public class WenshiFruitFactory implements FruitFactory {
public Fruit getApple() {
return new WenshiApple();
}
public Fruit getBanana() {
return new WenshiBanana();
}
}
// MainClass.java
public class MainClass {
public static void main(String[] args) {
FruitFactory ff = new NorthFruitFactory();
Fruit apple = ff.getApple();
apple.get();
Fruit banana = ff.getBanana();
banana.get();
FruitFactory ff2 = new SouthFruitFactory();
Fruit apple2 = ff2.getApple();
apple2.get();
Fruit banana2 = ff2.getBanana();
banana2.get();
FruitFactory ff3 = new WenshiFruitFactory();
Fruit apple3 = ff3.getApple();
apple3.get();
Fruit banana3 = ff3.getBanana();
banana3.get();
}
}
3.4 抽象工厂的起源
据说最早的应用是用来创建在不同操作系统的视窗环境下都能够运行的系统。比如在Windows与Unix系统下都有视窗环境的构件,在每一个操作系统中,都有一个视窗构件组成的构件家族。我们可以通过一个抽象角色给出功能描述,而由具体子类给出不同操作系统下的具体实现,如图:
可以发现上面产品类图有两个产品等级结构,分别是Button与Text;同时有两个产品族:Unix产品族与Windows产品族。
系统对产品对象的创建要求由一个工厂的等级结构满足。其中有两个具体工厂角色,即UnixFactory和WinFactory。UnixFactory对象负责创建Unix产品族中的产品,而WinFactory负责创建Windows产品族中的产品。
显然一个系统只能够在某一个操作系统的视窗环境下运行,而不能同时在不同的操作系统上运行。所以,系统实际上只能消费属于同一个产品族的产品。在现代的应用中,抽象工厂模式的使用范围已经大大扩大了,不再要求系统只能消费某一个产品族了。
3.5 "开放-封闭"原则
"开放-封闭"原则要求系统对扩展开放,对修改封闭。通过扩展达到增强其功能的目的。对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:增加产品族:Abstract Factory很好的支持了"开放-封闭"原则。
增加新产品的等级结构:需要修改所有的工厂角色,没有很好支持"开放-封闭"原则。
综合起来,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。
4,代理模式
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.html
/**
* @author Rollen-Holt 设计模式之 代理模式
*/
interface NetWork{
public abstract void browser();
}
/**
* Real 类代表用户上网的实际动作,比如查看网页
* */
class Real implements NetWork{
public void browser(){
System.out.println("上网浏览信息");
}
}
/**
* 此处使用代理类来完成中间代理的工作,屏蔽实现代理的细节
* */
class proxy implements NetWork{
private NetWork netWork;
proxy(NetWork netWork){
this.netWork = netWork;
}
public void browser(){
checkName();
((Real)this.netWork).browser();
}
private void checkName(){
// Other codes
}
}
class hello{
public static void main(String[] a){
new proxy(new Real()).browser();
}
}
4.1 什么是代理模式?
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。比如例子中是proxy代替Real对Real对象完成访问,并附加操作。4.2 代理模式有什么好处?
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。4.3 代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
5,单例模式
http://yangguangfu.iteye.com/blog/815944 又见搞笑版
http://www.iteye.com/topic/575052 这个还是比较全的
5.1 单例模式说明
它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量-唯一一个。(《设计模式-基于C#的工程化实现及扩展》,王翔)。也就是说,单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。
5.2 代码示例
解析如下:
1)首先,该Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单例的目的;
2)因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以可以定义一个私有的静态全局变量instance来保存该类的唯一实例;
3)必须提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,即通过if语句判断instance是否已被实例化,如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。
/**
* 实现单例访问Singleton的第一次尝试
*/
public class Singleton {
/**
* 单例对象实例
*/
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) { //line A
instance = new Singleton(); //line B
}
return instance;
}
}
在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单例规则。因此,需对上面代码修改。
/**
* 实现单例访问Singleton的第二次尝试
*/
public class Singleton {
/**
* 单例对象实例
*/
private static Singleton instance = null;
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
比起第一段代码仅仅在方法中多了一个synchronized修饰符,现在可以保证不会出线程问题了。但是这里有个很大(至少耗时比例上很大)的性能问题。除了第一次调用时是执行了SingletonKerriganB的构造函数之外,以后的每一次调用都是直接返回instance对象。返回对象这个操作耗时是很小的,绝大部分的耗时都用在synchronized修饰符的同步准备上,因此从性能上说很不划算。
6,适配器模式
http://zy19982004.iteye.com/blog/1415735
6.1 一个示例
适配器模式将一个接口转换成客户希望的另外一个接口。它使得原来由于接口不兼容而不能在一起工作的那些类可以一起工作。
光电套的鼠标是USB接口,键盘是PS2接口,可我的本本却没有PS2接口啊。于是跑到市场,淘了一个转接器。
PS2Port(PS2接口)
/**
* PS2接口,圆口
*/
public interface PS2Port {
public void workWithPS2();
}
USBPort(USB接口)
/**
* USB接口,U口
*/
public interface USBPort {
public void workWithUSB();
}
PS2ToUSB(对象适配器),将PS2接口装换成USB接口
/**
* 对象适配器
* 将PS2接口装换成USB接口
* 所以此类类型是USB接口(implements USBPort) + 成员变量ps2Port
* @author eason
*
*/
public class PS2ToUSB implements USBPort{
private PS2Port ps2Port;
public PS2ToUSB(PS2Port ps2Port) {
this.ps2Port = ps2Port;
}
@Override
public void workWithUSB() {
System.out.println("转换的关键在这里,本来是");
ps2Port.workWithPS2();
System.out.println("经过你的转换,现在是USB工作中");
}
}
TestAdapter(测试类),客户端
/**
* 测试类
* client
*/
public class TestAdapter {
public static void main(String[] args) {
//1.我现在有一个PS2接口
PS2Port ps2Port = new PS2Port() {
@Override
public void workWithPS2() {
System.out.println("PS2工作中");
}
};
//2.但是我需要的是一个USB接口啊,对我(client)来说,我只认识USB接口
//3.经过PS2ToUSB的转换,PS2接口变成了USB接口
USBPort ps2ToUsbPort = new PS2ToUSB(ps2Port);
ps2ToUsbPort.workWithUSB();
}
}
6.2 问题背景
我们已经在应用程序中设计了接口sampleOperation1, 然后我们又为了加快开发而购买了可以很好的完成此功能的第三方库, 然而第三方库的接口sampleOperation2和我们设计的接口sampleOperation1不同, 为了使这些接口不兼容的类可以一起工作, 我们应用Adapter模式将第三方库的接口sampleOperation2转换为我们的接口sampleOperation1 (也是客户希望的接口).
6.3 适配器模式有两种形式
一、类的适配器模式类图:
源代码:
package com.designpatterns.adapter;
/**
* 目标角色, 相当于我们的应用程序, sampleOperation1是我们开放给客户的接口
* @author suki
*/
public interface Target {
public void sampleOperation1();
}
/**
* 源角色,相当于第三方库
* @author suki
*/
public class Adaptee {
public Adaptee() {
}
public void sampleOperation2() {
System.out.println("Adaptee.sampleOperation2()");
}
}
/**
* 适配器角色
* 把第三方库的接口sampleOperation2转化为我们开放给客户的接口sampleOperation1
* * @author suki
*/
public class Adapter extends Adaptee implements Target {
public void sampleOperation1() {
this.sampleOperation2();
}
}
/**
* 客户端类
* @author suki
*/
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter();
target.sampleOperation1();
}
}
二、对象的适配器模式
在类的适配器模式中Adapter采用继承的方式复用Adaptee的接口,而在对象的适配器模式中Adapter则采用组合的方式实现Adaptee的复用
类图:
源代码
package com.designpatterns.adapterofobject;
/**
* 目标角色, 相当于我们的应用程序, sampleOperation1是我们开放给客户的接口
* @author suki
*/
public interface Target {
public void sampleOperation1();
}
/**
* 源角色,相当于第三方库
* @author suki
*/
public class Adaptee {
public Adaptee() {
}
public void sampleOperation2() {
System.out.println("Adaptee.sampleOperation2()");
}
}
/**
* 适配器角色
* 把第三方库的接口sampleOperation2转化为我们开放给客户的接口sampleOperation1
* @author suki
*/
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
super();
this.adaptee = adaptee;
}
public void sampleOperation1() {
adaptee.sampleOperation2();
}
}
/**
* 客户端类
* @author suki
*/
public class Client {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.sampleOperation1();
}
}
7,策略模式
http://yangguangfu.iteye.com/blog/815107 再次搞笑
http://www.cnblogs.com/justinw/archive/2007/02/06/641414.html 现在流行搞笑么?
7.1 什么是策略模式?
策略模式,又叫算法簇模式,就是定义了不同的算法族,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户。7.2 策略模式有什么好处?
策略模式的好处在于你可以动态的改变对象的行为。7.3 设计原则
设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口(c++z中可以用虚类),然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。下面是一个例子。策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响 到客户端的情况下发生变化。通常,策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
7.4 策略模式中有三个对象
(1) 环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。(2) 抽象策略对象:它可由接口或抽象类来实现。
(3) 具体策略对象:它封装了实现同不功能的不同算法。
利用策略模式构建应用程序,可以根据用户配置等内容,选择不同有算法来实现应用程序的功能。具体的选择有环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。
7.5 代码示例
package design.strategy;
/**
* 文件名称:design.strategy.IDiscount.java
* 说明:打折算法基类
* */
public interface IDiscount {
void discount() ;
}
package design.strategy;
/**
* 文件名称:design.strategy.DiscountHalf.java
* 说明:打折种类算法
* */
public class DiscountHalf implements IDiscount {
@Override
public void discount() {
System.out.println( "---半价---" );
}
}
package design.strategy;
/**
* 文件名称:design.strategy.DiscountEight.java
* 说明:打折种类算法
* */
public class DiscountEight implements IDiscount {
@Override
public void discount() {
System.out.println( "---八折---" );
}
}
package design.strategy;
/**
* 文件名称:design.strategy.StrategyFactory.java
* 说明:用于选择策略
*/
public class StrategyFactory {
IDiscount dis;
public StrategyFactory(int i) {
switch (i) {
case 0:
dis = new DiscountHalf();
break;
case 1:
dis = new DiscountEight();
break;
default:
dis = new DiscountEight();
break;
}
}
public void showMessage()
{
dis.discount() ;
}
}
package design.strategy;
/**
* 文件名称:design.strategy.Main.java
* 说明:测试类
* */
public class Main {
public static void main(String[] args) {
StrategyFactory factory = new StrategyFactory( 0 ) ;
factory.showMessage() ;
}
}