一:前置知识
设计模式: 人们有效解决某事而提炼出来的方法经验,被广泛认可,提供人们去参考。
作用:在程序设计中,设计模式可有效提高程序的可读性,可扩展性,减少程序设计的维护成本。
忠告:学习设计模式最好用一些故事和适用场景来辅助记忆,切忌不可死记。
二:设计模式引入
很久很久以前,张三和他的邻居们表面上生活在一起,为什么说是表面呢?因为存在着这样一个问题:缺乏交易,每个家庭独立的生产他们所需要的物品。这样每个人就不能做自己所擅长的东西,导致了生产成本高,效率低等缺点。而且缺乏统一的管理,比如说如果法律突然规定某件物品为违法产品需要禁用生产的话,需要强制禁止所有人生产该产品(一改全改,不符合开闭原则,代码耦合度高)。而且管理部门也不能准确知道那些家庭生产了某些产品(代码可读性差,维护成本高) ,如果有项有利的技术突破了,生产效率提高了,想要推广使用也得通知到位(程序可扩展性很差)
三:简单工厂模式
张三为了提升效率,发明了搅拌机,为其邻居们提供自助生产,邻居们需要自己操作,搅拌机可以生成豆浆、花生浆、玉米浆等各类产品,
改善了大家的生活水平,工厂(搅拌机)的概念出现了, 这时,可以称之为简单工厂模式。 搅拌机根据用户倒入的物品 ,生产给用户相应
的物品,但是前提是:
1.用户得知道能生产这个产品,例如能生产豆浆,但是不能放搅碎骨头
(程序复用的时候容易出错)
2.搅拌机(泛指工厂)如果榨另外一些东西,比如捣碎骨头:需要对豆浆机内部进行改装,如果改装失误,容易导致整个机器不可用
(导致程序可扩展性不好)
3.搅拌机的负担太重 (任何'东西'的子类都可以被生产,负担太重)
public interface Milk {
String getName();
}
//玉米汁
public class CornMilk implements Milk {
@Override
public String getName() {
return "玉米汁";
}
}
//花生汁
public class PeanutMilk implements Milk {
@Override
public String getName() {
return "花生汁";
}
}
//搅拌机
public class SimpleFactory {
Milk getMilk(String milkname){
switch (milkname){
case "豆浆" : return new SoyMilk();
case "玉米" : return new CornMilk();
case "花生" : return new PeanutMilk();
default:
System.out.println("不能搅拌"+milkname+"这种物品,Danger!!!");
return null;
}
}
//邻居
public class Neighborhood{
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory ();
//邻居们直接将物品倒入机器, 如果一些不支持的东西可能导致搅拌机损坏
System.out.println(simpleFactory.getMilk("豆浆"));
}
}
二:工厂方法模式
张三想啊,这样肯定不行啊,每当我要新增一个功能时候,我都要拆开我的搅拌机,万一那一天拆坏了怎么办法,于是他想出了这样一个办法,让每个搅拌机的功能单一,
这样既能提高工作效率,又能让每种搅拌机做他所擅长的。就像我们常见的可口可乐公司提供的饮料售卖机,可以根据用户的选择出可乐还是橙汁
//工厂类的抽象类
public interface Factory {
Milk getMilk();
}
//花生浆机
public class PeanutMilkFactory implements Factory {
@Override
public Milk getMilk() {
return new PeanutMilk();
}
}
//豆浆机
public class SoyMilkFactory implements Factory {
@Override
public Milk getMilk() {
return new SoyMilk();
}
}
//技术改进后的邻居,如果要使用某个搅拌机,必须了解这个搅拌机
public class FactroyMethodTest {
public static void main(String[] args) {
Factory factory = new CornMilkFactory();
System.out.println(factory.getMilk());
}
}
三:抽象工厂模式
但是出现了另外一个问题:
万一哪一天我的搅拌机种类太多,用户如果自助使用怎么知道我有这些东西呢.(代码耦合度略高)
张三想到了 , 就是提供一个柜台 ,不让用户直接操作搅拌机 , 而是交给张三 , 用户只需要告诉张三需要生产什么汁,并付相应的价格,让张三这个懂行的人操作即可,
张三看起来就像是这里的抽象工厂一样,屏蔽了用户直接和搅拌机(工厂)交互的机会.
public abstract class AbstractFactory {
abstract Milk getSoyMilk();
abstract Milk getPeanutMilk();
abstract Milk getCornMilk();
}
public class AbstractFactoryImpl extends AbstractFactory {
private SoyMilkFactory soyMilkFactory = new SoyMilkFactory();
private PeanutMilkFactory peanutMilkFactory = new PeanutMilkFactory();
private CornMilkFactory cornMilkFactory = new CornMilkFactory();
@Override
Milk getSoyMilk() {
return soyMilkFactory.getMilk();
}
@Override
Milk getPeanutMilk() {
return peanutMilkFactory.getMilk();
}
@Override
Milk getCornMilk() {
return cornMilkFactory.getMilk();
}
}
public class abstractMilkFactoryTest {
public static void main(String[] args) {
AbstractFactory abstractFactory = new AbstractFactoryImpl();
//直接找这个抽象的工厂看着工厂给出的能够提供的物品的清单挑选自己所需要的即可
System.out.println("abstractFactory = " + abstractFactory.getCornMilk());
}
}