如果想学习Java工程化、高性能及分布式、深入浅出。性能调优、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级架构进阶群:180705916,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家
另外还可以通过反射简洁生产过程,直接传入产品的类类型,生成对应的产品,示例如下:
Java代码
abstract class SMakeTea {
public abstract <T extends Tea> T 小猪带特效的奶茶制作工艺(Class<T> clz);
}
class SMe extends SMakeTea {
@Override
public <T extends Tea> T 小猪带特效的奶茶制作工艺(Class<T> clz) {
System.out.println("==============");
Tea tea = null;
try {
tea = (Tea) Class.forName(clz.getName()).newInstance();
tea.加奶();
tea.加茶();
tea.加料();
tea.打包();
} catch (Exception e) {
e.printStackTrace();
}
return (T) tea;
}
}
public class SStore {
public static void main(String[] args) {
SMe me = new SMe();
me.小猪带特效的奶茶制作工艺(ZhenZhuTea.class);
me.小猪带特效的奶茶制作工艺(YeGuoTea.class);
}
}
六. 抽象工厂模式(Abstract Factory Pattern)
代码示例
Java代码
//抽象产品类1
abstract class Drink {
public abstract void drink();
}
//抽象产品类2
abstract class Snack {
public abstract void snack();
}
//具体产品类们
class MilkTea extends Drink {
@Override public void drink() { System.out.println("一杯奶茶"); }
}
class Juice extends Drink {
@Override public void drink() { System.out.println("一杯果汁"); }
}
class HandGrab extends Snack {
@Override public void snack() { System.out.println("一个手抓饼"); }
}
class FishBall extends Snack {
@Override public void snack() { System.out.println("一碗鱼蛋"); }
}
//抽象工厂类
abstract class MakeFood {
abstract Drink createMakeDrink();
abstract Snack createMakeSnack();
}
//具体工厂类1
class FirstXiaoDi extends MakeFood {
@Override public Drink createMakeDrink() { return new MilkTea(); }
@Override public Snack createMakeSnack() { return new HandGrab(); }
}
//具体工厂类2
class SecondXiaoDi extends MakeFood {
@Override public Drink createMakeDrink() { return new Juice(); }
@Override public Snack createMakeSnack() { return new FishBall(); }
}
//客户端调用
public class Store {
public static void main(String[] args) {
//初始化两个小弟
MakeFood xiaodi1 = new FirstXiaoDi();
MakeFood xiaodi2 = new SecondXiaoDi();
for(int i = 0;i < 4 ;i++) {
System.out.println("====== 根据订单配餐: ======");
Drink drink = buyDrink() == 0 ?
xiaodi1.createMakeDrink() : xiaodi2.createMakeDrink();
Snack snack = buySnack() == 0 ?
xiaodi1.createMakeSnack() : xiaodi2.createMakeSnack();
drink.drink();
snack.snack();
}
}
/* 模拟用户点饮料,0代表要奶茶,1代表要果汁 */
private static int buyDrink() { return new Random().nextInt(2); }
/* 模拟用户点小吃,0代表要手抓饼,1代表要鱼蛋 */
private static int buySnack() { return new Random().nextInt(2); }
}
输出结果:
两个名词(产品等级结构与产品族)
产品等级结构(继承):
比如这里的抽象类是Drink(饮料),子类有奶茶,果汁,然后抽象饮料与具体饮料构成了一个产品等级结构,抽象饮料是父类,具体饮料是其子类。
产品族
同一工厂生产的,位于不同产品等级结构的一组产品,比如这里的奶茶和果汁属于饮料结构的一组产品,而手抓饼和鱼蛋则属于小吃结构的一组产品。
四个角色与UML类图
抽象工厂模式适用于创建的对象有多个相互关联或依赖的产品族;抽象工厂模式隔离具体类的生成,接口与实现分离,增加新的产品族很方便;但是扩展新的产品等级结构麻烦,需要修改抽象工厂,具体工厂类也要更改。
两个彼此间没太大关联的类,想进行交互完成某些事情,不想直接去修改各自的接口,可以添加一个中间类,让他来协调两个类间的关系,完成相关业务,这种模式就叫适配器模式。
然后分为:类适配器和对象适配器两种,前者和适配者是继承关系,后者与适配者则是引用关系。
对象适配器支持传入一个被适配器对象,因此可以做到对多种被适配接口进行适配。而类适配器直接继承,无法动态修改,所以一般情况下对象适配器使用得更多!(Java不支持多重继承!!!)
对象适配器例子(用得较多)
Java代码
/* 目标接口 */
interface Chinese {
void speakChinese(String string);
}
/* 需要适配的类 */
class English {
void speakEnglish(String string) { System.out.println("【英语】" + string); }
}
/* 适配器 */
class Translator implements Chinese{
private English english = new English();
Translator(English english) { this.english = english; }
@Override public void speakChinese(String string) { english.speakEnglish(string); }
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
Chinese chinese = new Translator(new English());
chinese.speakChinese("那你很棒棒哦!");
}
}
输出结果:
类适配器例子
Java代码
/* 类适配器 */
class ClassTranslator extends English implements Chinese {
@Override public void speakChinese(String string) { speakEnglish(string); }
}
/* 客户端调用 */
public class ClientC {
public static void main(String[] args) {
ClassTranslator translator = new ClassTranslator();
translator.speakChinese("你也很好啊!");
}
}
输出结果:
除此之外还有个缺省适配器模式的名词,简单点说就是不需要实现接口中提供的所有方法时,先写一个抽象类实现这个接口,然后为每个方法提供一个默认实现(空方法),然后选择性覆盖某些方法实现需求,又称单接口适配器模式。
动态的给对象添加一些额外的职责,就增加功能来说,装饰者模式比起生成子类更加灵活!就是想替代多重层继承的模式。其实就是一层套一层。
代码示例
Java代码
/* 抽象组件 */
abstract class Tea {
private String name = "茶";
public String getName() { return name; }
void setName(String name) { this.name = name; }
public abstract int price();
}
/* 具体组件 */
class MilkTea extends Tea {
MilkTea() { setName("奶茶"); }
@Override public int price() { return 5; }
}
class LemonTea extends Tea{
LemonTea() { setName("柠檬茶"); }
@Override public int price() { return 3; }
}
/* 抽象装饰类 */
abstract class Decorator extends Tea{
public abstract String getName();
}
/* 具体装饰类 */
class ZhenZhu extends Decorator {
Tea tea;
ZhenZhu(Tea tea) { this.tea = tea; }
@Override public String getName() { return "珍珠" + tea.getName(); }
@Override public int price() { return 2 + tea.price(); }
}
class YeGuo extends Decorator{
//...
}
class JinJu extends Decorator{
//...
}
class HongDou extends Decorator{
//...
}
/* 客户端调用 */
public class Store {
public static void main(String[] args) {
Tea tea1 = new MilkTea();
System.out.println("你点的是:" + tea1.getName() + " 价格为:" + tea1.price());
Tea tea2 = new LemonTea();
tea2 = new JinJu(tea2);
System.out.println("你点的是:" + tea2.getName() + " 价格为:" + tea2.price());
Tea tea3 = new MilkTea();
tea3 = new ZhenZhu(tea3);
tea3 = new YeGuo(tea3);
tea3 = new HongDou(tea3);
tea3 = new JinJu(tea3);
System.out.println("你点的是:" + tea3.getName() + " 价格为:" + tea3.price());
}
}
输出结果:
部分-整体模式,把具有相似的一组对象当做一个对象处理,用一种树状的结构来组合对象,再提供统一的方法去访问相似的对象,以此忽略掉对象与对象容器间的差别。
根节点,枝结点,叶子结点三个名词需要理解,类比上图,根节点是菜单,枝结点是饮料菜单和小吃菜单,叶子结点是奶茶,果汁,手抓饼和鱼蛋!
代码示例
Java代码
/* 抽象组件 */
abstract class AbstractMenu {
public abstract void add(AbstractMenu menu);
public abstract AbstractMenu get(int index);
public abstract String getString();
}
/* 容器组件 */
class Menu extends AbstractMenu {
private String name;
private String desc;
private List<AbstractMenu> menus = new ArrayList<>();
Menu(String name, String desc) {
this.name = name;
this.desc = desc;
}
@Override public void add(AbstractMenu menu) { menus.add(menu); }
@Override public AbstractMenu get(int index) { return menus.get(index); }
@Override public String getString() {
StringBuilder sb = new StringBuilder("\n【菜单】:" + name + " 信息:" + desc + "\n");
for (AbstractMenu menu: menus) { sb.append(menu.getString()).append("\n"); }
return sb.toString();
}
}
/* 叶子组件 */
class MilkTea extends AbstractMenu {
private String name;
private String desc;
private int price;
MilkTea(String name, String desc, int price) {
this.name = name;
this.desc = desc;
this.price = price;
}
@Override public void add(AbstractMenu menu) { /*未使用*/ }
@Override public AbstractMenu get(int index) { return null; }
@Override public String getString() {
return " - 【奶茶】* " + name + " 标注:" + desc + " 价格:" + price;
}
}
class MilkTea extends AbstractMenu {
//...
}
class HandCake extends AbstractMenu {
//...
}
class FishBall extends AbstractMenu {
//...
}
/* 客户端调用 */
public class Store {
public static void main(String[] args) {
AbstractMenu mainMenu = new Menu("大菜单", "包含所有子菜单");
AbstractMenu drinkMenu = new Menu("饮品菜单", "都是喝的");
AbstractMenu eatMenu = new Menu("小吃菜单", "都是吃的");
AbstractMenu milkTea = new MilkTea("珍珠奶茶", "奶茶+珍珠", 5);
AbstractMenu juice = new Juice("鲜榨猕猴桃枝", "无添加即榨", 8);
AbstractMenu ball = new FishBall("咖喱鱼蛋", "微辣", 6);
AbstractMenu cake = new HandCake("培根手抓饼", "正宗台湾风味", 8);
drinkMenu.add(milkTea);
drinkMenu.add(juice);
eatMenu.add(ball);
eatMenu.add(cake);
mainMenu.add(drinkMenu);
mainMenu.add(eatMenu);
System.out.println(mainMenu.getString());
}
}
输出结果:
基于单一职责原则,如果系统中的类存在多个变化的维度,通过该模式可以将这几个维度分离出来, 然后进行独立扩展。这些分离开来的维度,通过在抽象层持有其他维度的引用来进行关联,就好像在两个维度间搭了桥一样,所以叫桥接模式。
代码示例(变化的三个维度:配餐,扒类)
Java代码
/* 抽象部分 */
abstract class Rations {
abstract String rations();
}
/* 扩展抽象部分 */
class Rice extends Rations {
@Override public String rations() { return "饭"; }
}
class Spaghetti extends Rations {
@Override public String rations() { return "意粉"; }
}
/* 实现部分 */
abstract class Steak {
Rations rations;
Steak(Rations rations) { this.rations = rations; }
abstract String sale();
}
/* 具体实现部分 */
class BeefSteak extends Steak{
BeefSteak(Rations rations) { super(rations); }
@Override public String sale() { return "牛扒"+ (rations == null ? "" : rations.rations()); }
}
class PorkSteak extends Steak {
PorkSteak(Rations rations) { super(rations); }
@Override public String sale() { return "猪扒"+ (rations == null ? "" : rations.rations()); }
}
/* 客户端调用 */
public class Restaurant {
public static void main(String[] args) {
System.out.println("\n" + new Date(System.currentTimeMillis()));
System.out.println("==================");
Steak steak1 = new BeefSteak(new Rice());
System.out.println("卖出了一份:" + steak1.sale());
Steak steak2 = new PorkSteak(new Spaghetti());
System.out.println("卖出了一份:" + steak2.sale());
Steak steak3 = new PorkSteak(null);
System.out.println("卖出了一份:" + steak3.sale());
System.out.println("==================");
}
输出结果:
要求一个子系统的外部与内部的通信必须通过一个统一的对象进行,外观模式提供一个高层次的接口,使得子系统更易于使用。(其实就是封装,用于解决类与类间的依赖关系,比如本来是:玩家依赖于:Q,A,E,R等键位对象,现在变成只依赖与脚本对象从而降低了类间的耦合度。)
代码示例
Java代码
/* 子系统 */
class A {
String a() { return "A"; }
}
class Q { /* ... */ }
class Space { /* ... */ }
class LeftClick { /* ... */ }
/* 外观类 */
class JiaoBen {
A a;
Q q;
LeftClick leftClick;
Space space;
JiaoBen() {
a = new A();
leftClick = new LeftClick();
q = new Q();
space = new Space();
}
String 锐雯() {
StringBuilder sb = new StringBuilder();
sb.append(q.q()).append(" + ");
sb.append(space.space()).append(" + ");
sb.append(a.a()).append(" + ");
sb.append(leftClick.leftClick()).append(" + ");
sb.append(q.q()).append(" + ");
sb.append(space.space()).append(" + ");
sb.append(a.a()).append(" + ");
sb.append(leftClick.leftClick()).append(" + ");
sb.append(q.q()).append(" + ");
sb.append(space.space()).append(" + ");
sb.append(a.a()).append(" + ");
sb.append(leftClick.leftClick()).append("\n");
return sb.toString();
}
}
/* 客户端调用 */
public class XLoLer {
public static void main(String[] args) {
JiaoBen jiaoBen = new JiaoBen();
System.out.println("=== 锐雯一键光速QA ===\n" + jiaoBen.锐雯());
}
}
输出结果:
当存在多个相同对象时,可以使用享元模式减少相同对象创建引起的内存消耗,提高程序性能。说到共享,还分内部状态与外部状态。
内部状态:固定不变可共享的的部分,存储在享元对象内部,比如例子中的花色
外部状态:可变不可共享的部分,一般由客户端传入享元对象内部,比如例子里的大小。
示例代码
Java代码
/* 抽象对象的父类 */
abstract class Card {
abstract void showCard(String num); //传入外部状态参数,大小
}
/* 具体享元对象 */
public class SpadeCard extends Card{
public SpadeCard() { super(); }
@Override public void showCard(String num) { System.out.println("黑桃:" + num); }
}
public class HeartCard extends Card { /* ... */ }
public class ClubCard extends Card { /* ... */ }
public class DiamondCard extends Card { /* ... */ }
/* 享元工厂 */
public class PokerFactory {
static final int Spade = 0; //黑桃
static final int Heart = 1; //红桃
static final int Club = 2; //梅花
static final int Diamond = 3; //方块
public static Map<Integer, Card> pokers = new HashMap<>();
public static Card getPoker(int color) {
if (pokers.containsKey(color)) {
System.out.print("对象已存在,对象复用...");
return pokers.get(color);
} else {
System.out.print("对象不存在,新建对象...");
Card card;
switch (color) {
case Spade: card = new SpadeCard(); break;
case Heart: card = new HeartCard(); break;
case Club: card = new ClubCard(); break;
case Diamond: card = new DiamondCard(); break;
default: card = new SpadeCard(); break;
}
pokers.put(color,card);
return card;
}
}
/* 客户端调用 */
public class Player {
public static void main(String[] args) {
for (int k = 0; k < 10; k ++){
Card card = null;
//随机花色
switch ((int)(Math.random()*4)) {
case 0: card = PokerFactory.getPoker(PokerFactory.Spade); break;
case 1: card = PokerFactory.getPoker(PokerFactory.Heart); break;
case 2: card = PokerFactory.getPoker(PokerFactory.Club); break;
case 3: card = PokerFactory.getPoker(PokerFactory.Diamond); break;
}
if(card != null) {
//随机大小
int num = (int)(Math.random()*13 + 1);
switch (num) {
case 11: card.showCard("J"); break;
case 12: card.showCard("Q"); break;
case 13: card.showCard("K"); break;
default: card.showCard(num+""); break;
}
}
}
}
}
输出结果:
未完待续。。。
网友评论