[设计模式]简单工厂(Simply Factory)
简单工厂Simple Factory
时常能在大几百行甚至几千行的类代码中看到如下代码的身影:
class AnimalShow { //根据不同的动物名称显示对应的动物 public void DisplayAnimal(String animalName) { Animal animal; if(animalName == "dog") { animal = new Dog(); } if (animalName == "cat") { animal = new Cat(); } animal.display(); } }
高级一点的会用上枚举,可能会写成这样:
class Navigator { enum userType { visitor, user, vip }; //根据不同的用户身份,导航到相应的页面 public void Navigation(userType currentUser) { String targetURL = ""; switch(currentUser) { case userType.visitor: targetURL = "/visitor.html";//这里其实相当于是一次获取String的实例的操作;等价于targetURL = new String("/visitor.html"); break; case userType.user: targetURL = "/user.html"; break; case userType.vip: targetURL = "/vip.html"; break; } NavigateTo(targetURL);//导航到相应的页面 } }
我们都知道,在实际的开发中,唯一不变的就是变化!
特别是第一段程序中的if{}部分,还有第二段程序中的switch{}部分,都是三天两头就有可能被要求修改的。而实际的项目中,像这样的主体类可能会有成百上千行代码,这些if/switch到时只会被淹没在代码海中,每次修改都要在茫茫码海中找到它们,并且再作出修改,这种事情做多了久而久之很消人志气。
还有一点非常值得注意——这样的代码一点都不适合复用,直接就在主体类中进行硬绑定显然对今后的修改非常不利。
解决的办法可以利用简单工厂模式,使类和类之间解耦。
以第二个例子哪来开刀。将容易改变的switch{}部分提取出来,构建成一个生产实例的工厂 —— 即用户丢入需求,工厂则依照用户的需求返回相应的实例。
运用简单工厂修改后的代码如下:
1.工厂类:
//URL工厂,专门负责生产各种工厂实例 class URLFactory { //根据不同的用户需求返回不同的URL实例 public String GetURL(userType currentUser) { String targetURL = ""; switch (currentUser) { case userType.visitor: targetURL = "/visitor.html"; break; case userType.user: targetURL = "/user.html"; break; case userType.vip: targetURL = "/vip.html"; break; } return targetURL; } }
2.主体类:
class Navigator { enum userType { visitor, user, vip }; public void Navigation(userType currentUser) { URLFactory urlFactory = new URLFactory(); String targetURL = urlFactory.GetURL(currentUser); NavigateTo(targetURL); } }
也许有人要说了,我原来好端端地一个类,你楞要拆成两个,这不是增加了代码维护的难度么?
表面上看起来好像是这样,其实不然,这多出的一个类使得原先的主体类变得更加的清楚,增加了代码的可读性,而且将所有容易改变的部分都提取出来之后(此例中只有获取URL这个地方容易改变),这就使得今后对代码的维护只要对这几个类进行就好了,代码少、逻辑清晰,实在是方便修改。
而且更重要的是,这样一来,这个根据用户不同身份而取得不同URL的方法将变得可以复用。
这其实又涉及到设计模式的另外一个重要思想——“依赖倒置”
//to be continued.