设计模式学习笔记(开篇)-抽象工厂 工厂模式 简单工厂(1)

之前,我一直对设计模式有很多不理解,就像简单工厂和工厂模式有什么区别,代理模式/面模式/适配器模式/装饰器模式等都是通过组合包装另一个类。他们之间又什么区别。我甚至认为这就是一个实现方式。同时,继承和装饰器模式都能为一个类添加新的动能,它们之间又有什么不一样。为了搞懂这些问题。我特地去重新学习了设计模式。这里,我学习的书籍是《Head First设计模式(中文版)》 和 《Gof设计模式》

《Head First设计模式》这本书,比较适合初学者。该书介绍设计模式的方式通俗易懂,主要通过故事,对话的方式向我们介绍了设计模式实现,分类,差别,同时向我们展示了常用的设计原则。 对了,这本书的代码实现语言是java

《Gof设计模式》适合要深入的人,主要实现语言是C++ 和 smalltalk。这本书被喻为经典。说实在我看了两遍才看懂一些。这本的架构比较清晰。每个设计模式都系统的介绍了它的动机,适用范围,优缺点,代码实现等。但是举的例子比较不好懂。可能我是比较生活化的人。


好了,书籍介绍完了,下面进入我们的主题-抽象工厂模式  工厂模式  简单工厂模式。

我们知道,这三种设计模式定义都是“定义创建对象的接口”。都是把创建对象这个过程集中化。开发者只需要维护一个类,对开发者来说,方便管理。对于使用者来说,他不需要知道对象的具体创建过程(一个实例由哪个类实现,或者需要几个类共同实现)。他只需要知道和记得这个接口可以创建他们所需要的实例即可。这样很方便使用者使用。

我们的场景是:

 修理工,修理设备时常常需要一些工具如:大锤子,小锤子,一字螺丝刀,十字螺丝刀,剪刀等,实现语言PHP

工具接口:

interface IBasicTool {
    public function using();
} 

工具具体实现:

class SmallHammer implements IBasicTool {
	public function  __construct() {
		echo "SmallHammer";
	}
	public function using() {
		
	}	
}
class BigHammer implements IBasicTool {
	public function  __construct() {
		echo "BigHammer";
	}
	public function using() {
		
	}	
}
class StraightScrewdriver implements IBasicTool {
	public function  __construct() {
		echo "StraightScrewdriver";
	}
	public function using() {
		
	}	
}
class CrossScrewdriver implements IBasicTool {
	public function  __construct() {
		echo "CrossScrewdriver";
	}
	public function using() {
		
	}	
}

class Scissors implements IBasicTool {
	public function  __construct() {
		echo "Scissors";
	}
	public function using() {

	}	
}

简单工厂模式

(1)PHP代码实现

//可视为第三方提供的接口
class SimpleFactory {
	public function createTool($flag) {
		if($flag == 'SmallHammer') {
			return new SmallHammer();
		}
		else if($flag == 'BigHammer') {
			return new BigHammer()
		}
		else if($flag == 'StraightScrewdriver') {
			return new StraightScrewdriver()
		}
		else if($flag == 'CrossScrewdriver') {
			return new CrossScrewdriver();
		}
		return null;
	}
}
//使用者
class Client {
 $Factory = new SimpleFactory();
 $Factory->create("SmallHammer");
}

从上面例子中,我们可以知道。简单工厂模式的优点是:

使用者只需要关注 SimpleFactory 这个工厂类就好。要想得到一个小锤子就通过createTool(SmallHammer)。至于到底使用哪个类,怎么实现,使用者并不需要知道,也不关心。这就实现了使用者和工具具体实现的解耦。 

简单工厂的缺点是:

当要扩展新工具的时候,需要重新修改工厂方法。违反OCP(开发-关闭原则)原则。简单工厂不适合复杂的对象创建,这样会出现类似if else这样的逻辑去维护。比如你要创建工具A 那你就需要 if else($flag=='A') 。这对于开发者来说是不友好的。同时当我不只是要选择工具,而且要选择工具制造商时。那怎么办。 可能就需要修改的工厂的方法了。比如:

class SimpleFactory {
	public function createTool($flag, $country) {
		if($country == 'China') {
			if($flag == 'SmallHammer') {
				return new SmallHammer();
			}
			else if($flag == 'BigHammer') {
				return new BigHammer()
			}
			else if($flag == 'StraightScrewdriver') {
				return new StraightScrewdriver()
			}
			else if($flag == 'CrossScrewdriver') {
				return new CrossScrewdriver();
			}
		
		}
		else if( $country == 'USA') {
			if($flag == 'SmallHammer') {
				return new USASmallHammer();
			}
			else if($flag == 'BigHammer') {
				return new USABigHammer()
			}
			else if($flag == 'StraightScrewdriver') {
				return new USAStraightScrewdriver()
			}
			else if($flag == 'CrossScrewdriver') {
				return new USACrossScrewdriver();
			}			
		}
		return null;
	}

这样不仅违反了OCP原则。同时对原来的使用者来说,他们可能需要修改之前的代码才能适用你的接口。比如甲君在之前调用了createTool("smallHammer")。 现在SimpleFactory这个类,在他不知情的情况下,被修改了。甲君的原有的程序就会报错。同时就算你通知的甲君,对于使用者(程序员都不喜欢该写过的程序)来说,也不是很想改。

同时对于接口开发这样也很痛苦,这么多的if else 看着就晕。更何况现在只是添加了一个产地,之后谁知道还什么要添加。

那么我们要怎么解决这个问题?我在下一篇介绍工厂方法时再说。

猜你喜欢

转载自blog.csdn.net/H_L_S/article/details/85364503