@huangyichun
2017-08-30T15:50:18.000000Z
字数 16247
阅读 1004
设计模式
观察者
状态
通过封装、继承、多态把程序的耦合度降低。
UML类图: 依赖、组合、继承、实现、聚合、关联
:子类必须能够替换掉他们的父类型。
面向对象的语言有三大特性:封装、继承、多态,里氏替换原则就是依赖于继承、多态这两大特性,它的原则就是只要父类能出现的地方子类就能出现,而且不会报错,但是子类能出现的地方,父类不一定能出现,术语就是 —— 抽象。
一个软件实体如果使用的时一个父类的话,那么一定适用于其子类,而且它察觉不出父类和子类的区别。
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。这里的“接口”往往有两种不同的含义:一种是指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象;另外一种是指某种语言具体的“接口”定义,有严格的定义和结构,比如Java语言中的interface。
也叫最小知识原则,如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的互相作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
简单工厂模式解决的问题是如何去实例化一个合适的对象。
简单工厂模式的核心思想就是:有一个专门的类来负责创建实例的过程。
具体来说,把产品看着是一系列的类的集合,这些类是由某个抽象类或者接口派生出来的一个对象树。而工厂类用来产生一个合适的对象来满足客户的要求。
如果简单工厂模式所涉及到的具体产品之间没有共同的逻辑,那么我们就可以使用接口来扮演抽象产品的角色;如果具体产品之间有功能的逻辑或,我们就必须把这些共同的东西提取出来,放在一个抽象类中,然后让具体产品继承抽象类。为实现更好复用的目的,共同的东西总是应该抽象出来的。
设计一个计算器的,完成加减乘除操作。
public class Operation {//父类
private double numberA = 0;
private double numberB = 0;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public double getResult(){
double result =0;
return result;
}
}
public class OperationAdd extends Operation {//加法操作
@Override
public double getResult() {
return getNumberA() + getNumberB();
}
}
public class OperationDiv extends Operation {//除法操作
@Override
public double getResult() {
if(getNumberB() == 0){
throw new RuntimeException("除数不能为0");
}
return getNumberA() / getNumberB();
}
}
public class OperationMul extends Operation {//乘法操作
@Override
public double getResult() {
return getNumberA() * getNumberB();
}
}
public class OperationSub extends Operation{//减法操作
@Override
public double getResult() {
return getNumberA() - getNumberB();
}
}
public class OperationFactory {//简单工厂模式
/**
* 采用多态,根据传入的参数,返回父类引用子类对象
* @param operate
* @return
*/
public static Operation createOperate(String operate) {
Operation operation;
switch (operate) {
case "+":
operation = new OperationAdd();
break;
case "-":
operation = new OperationDiv();
break;
case "*":
operation = new OperationMul();
break;
case "/":
operation = new OperationDiv();
break;
default:
throw new RuntimeException("输入的符号不正确");
}
return operation;
}
}
public class Main {//测试方法
public static void main(String[] args) {
Operation operation = OperationFactory.createOperate("*");
operation.setNumberA(10);
operation.setNumberB(2);
System.out.println(operation.getResult());
}
}
定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
这个模式涉及到三个角色:
● 环境(Context)角色:持有一个Strategy的引用。
● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
商场打折案例:
/**
* 抽象算法类
*/
public interface CashStrategy {
double acceptCash(double money);
}
/**
* 返利200返100等
*/
public class CashReturnStrategy implements CashStrategy {
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
public CashReturnStrategy(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
if(money >= moneyCondition){
money = money - (int)(money / moneyCondition) * moneyReturn;
}
return money;
}
}
/**
* 打折
*/
public class CashRebateStrategy implements CashStrategy {
private double moneyRebate = 1d;//打折额度
public CashRebateStrategy(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
/**
* 正常价格
*/
public class CashNomalStrategy implements CashStrategy{
@Override
public double acceptCash(double money) {
return money;
}
}
/**
* 策略模式初始版本
* Created by huang on 17-4-12.
*/
public class CashContext {
private CashStrategy cashStrategy;
public CashContext(CashStrategy cashStrategy) {
this.cashStrategy = cashStrategy;
}
public double getResult(double money){
return cashStrategy.acceptCash(money);
}
}
/**
* 策略模式与简单工厂模式结合
*/
public class CashContext_2 {
CashStrategy cashStrategy;
public CashContext_2(String type) {
switch (type){
case "正常收费":
cashStrategy = new CashNomalStrategy();
break;
case "满300返100":
cashStrategy = new CashReturnStrategy(300, 100);
break;
case "打8折":
cashStrategy = new CashRebateStrategy(0.8);
break;
}
}
public double getResult(double money){
return cashStrategy.acceptCash(money);
}
}
public class Main {
public static void main(String[] args) {
CashStrategy cashStrategy = new CashReturnStrategy(500,200);
CashContext cashContext = new CashContext(cashStrategy);
double money = cashContext.getResult(750.6);
System.out.println(money);
System.out.println("----------------------");
//策略模式与简单工厂模式结合
CashContext_2 cashContext_2 = new CashContext_2("打8折");
money = cashContext_2.getResult(300);
System.out.println(money );
}
}
Jdk中使用策略模式:
线程池中当等待队列满时,处理策略有很多种,可以根据需求传入。
动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
在装饰模式中的各个角色有:
(1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
(2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
(3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
(4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。
IO流采用了装饰者模式,其中InputStream为抽象构件,而FileInputStream, ObjectInputStream等为具体构件,FilterInputStream为装饰角色,它下面的子类,BufferedInputStream,DateInputStream等为具体装饰角色。
/**
* 抽象对象,如果只有一个具体对象可以不要这个类
*/
public interface Componet {
void operation();
}
/**
* 具体对象
*/
public class PersonComponent implements Componet{
private String name;
public PersonComponent(String name) {
this.name = name;
}
@Override
public void operation() {
System.out.println("装扮对象是"+name);
}
}
/**
* 抽象装饰类
*/
public class FineryDecorator implements Componet {
private Componet componet;
public FineryDecorator(Componet componet) {//装饰对象
this.componet = componet;
}
@Override
public void operation() {
componet.operation();
}
}
/**
* 具体装饰类
*/
public class LeatherDecorator extends FineryDecorator {
public LeatherDecorator(Componet componet) {
super(componet);
}
@Override
public void operation() {
super.operation();
System.out.println("穿皮鞋");
}
}
/**
*具体装饰类
*/
public class BigTrouserDecorator extends FineryDecorator {
public BigTrouserDecorator(Componet componet) {
super(componet);
}
@Override
public void operation() {
super.operation();
System.out.println("穿上垮库");
}
}
/**
*具体装饰类
*/
public class TShirtsDecorator extends FineryDecorator{
public TShirtsDecorator(Componet componet) {
super(componet);
}
@Override
public void operation() {
super.operation();
System.out.println("穿上T恤");
}
}
/**
* 测试装饰模式
*/
public class Main {
public static void main(String[] args) {
PersonComponent person = new PersonComponent("小菜");
FineryDecorator decorator = new LeatherDecorator(
new TShirtsDecorator(
new BigTrouserDecorator(person)));
decorator.operation();
}
}
/**
* 享元类
*/
public interface FlyWeight {
String getColor();
void display(Coordinate c);
}
package flyWeight;
/**
* Created by huang on 17-5-12.
*/
public class ConcreteFlyWeight implements FlyWeight {
private String color;
public ConcreteFlyWeight(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void display(Coordinate c) {
System.out.println("棋子颜色"+color);
System.out.println("棋子位置"+c.getX() + " "+ c.getY());
}
}
package flyWeight;
/**
* 外部状态UnSharedConcreteFlyWeight
*/
public class Coordinate {
private int x, y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
package flyWeight;
import java.util.HashMap;
import java.util.Map;
/**
* 享元工厂类
*/
public class FlyWeightFactory {
// ThreadPoolExecutor 线程池,相当于享元工厂
//享元池
private static Map<String, FlyWeight> map = new HashMap<>();
public static FlyWeight getChess(String color){
if(map.get(color) != null)
return map.get(color);
else{
FlyWeight flyWeight = new ConcreteFlyWeight(color);
map.put(color, flyWeight);
return flyWeight;
}
}
}
package flyWeight;
import org.junit.Test;
/**
* Created by huang on 17-5-12.
*/
public class Client {
@Test
public void test(){
FlyWeight flyWeight1 = FlyWeightFactory.getChess("红色");
FlyWeight flyWeight2 = FlyWeightFactory.getChess("红色");
System.out.println(flyWeight1 == flyWeight2);
//添加外部状态
flyWeight1.display(new Coordinate(3, 4));
}
}
package observer;
import java.util.ArrayList;
import java.util.List;
/**
* 主题
*/
public class Subject {
protected List<Observer> list = new ArrayList<>();
public void registerObserver(Observer observer){
list.add(observer);
}
public void removeObserver(Observer observer){
list.remove(observer);
}
public void notifyAllObserver(){
list.forEach(observer -> observer.update(this));
}
}
package observer;
/**
* 观察者
*/
public interface Observer {
void update(Subject subject);
}
package observer;
/**
* 具体主题
*/
public class ConcreteSubject extends Subject{
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObserver();
}
}
package observer;
/**
* 具体观察者
*/
public class ObserverA implements Observer {
private int myState;
public int getMyState() {
return myState;
}
public void setMyState(int myState) {
this.myState = myState;
}
@Override
public void update(Subject subject) {
setMyState(((ConcreteSubject)subject).getState());
}
}
package observer;
/**
*客户端
*/
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ObserverA obs1 = new ObserverA();
ObserverA obs2 = new ObserverA();
ObserverA obs3 = new ObserverA();
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
subject.setState(100);
System.out.println("-------------------");
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
subject.setState(200);
System.out.println("-------------------");
System.out.println(obs1.getMyState());
System.out.println(obs2.getMyState());
System.out.println(obs3.getMyState());
}
}
工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延续到其子类。
public interface Car {
void run();
}
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪再跑!");
}
}
public class Benz implements Car{
@Override
public void run() {
System.out.println("奔驰再跑");
}
}
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
public interface CarFactory {
Car createCar();
}
public class AudiFactory implements CarFactory {
@Override
public Car createCar() {
return new Audi();
}
}
public class BenzFactory implements CarFactory {
@Override
public Car createCar() {
return new Benz();
}
}
public class BydFactory implements CarFactory {
@Override
public Car createCar() {
return new Byd();
}
}
public class Client {
public static void main(String[] args) {
Car c1 = new AudiFactory().createCar();
c1.run();
Car c2 = new BydFactory().createCar();
c2.run();
}
}
适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由接口不兼容而不能一起工作的那些类可以一起工作。
组成:
1)Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
2)Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
3)Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
/**
* 目标抽象类
*/
public interface Target {
void handleReq();
}
/**
* 被适配的类,
* 相当于例子中的,PS/2键盘
* Created by huangyichun on 2017/2/7.
*/
public class Adaptee {
public void request(){
System.out.println("可以完成用户的需求");
}
}
/*
* 适配器
*/
public class Adapter2 implements Target {
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleReq() {
adaptee.request();
}
}
/**
* 适配器(类适配器方式)
* 相当于usb和ps/2转接口
* Created by huangyichun on 2017/2/7.
*/
public class Adapter extends Adaptee implements Target{
@Override
public void handleReq() {
super.request();
}
}
/**
* 被适配的类,
* 相当于例子中的,PS/2键盘
* Created by huangyichun on 2017/2/7.
*/
public class Adaptee {
public void request(){
System.out.println("可以完成用户的需求");
}
}
/**
* 客户端类
* 相当于例子中的笔记本,只有USB接口
* Created by huangyichun on 2017/2/7.
*/
public class Client {
public static void main(String[] args) {
Client c = new Client();
Adaptee a = new Adaptee();
// Target t = new Adapter();
Target t = new Adapter2(a);
t.handleReq();
}
}
在JDK中使用了适配器模式,如下图
将InputStream类型通过InputStreamReader转换成Reader类型,StreamDecoder中包含着InputStream的引用,可以通过源码查看,这是因为Byte类型到char类型需要经过编码。
组合模式,将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
JDK中AWT包和Swing包的设计是基于组合模式,在这些界面包中为用户提供了大量的容器构件(如Container)和成员构件(如Checkbox、Button和TextComponent等),他们都是继承、关联自抽象组件类Component。
**
* 抽象组件
* Created by huangyichun on 2017/2/8.
*/
public interface AbstractFile {
void killVirus();//杀毒
}
class ImageFile implements AbstractFile{
private String name;
public ImageFile(String name) {
this.name = name;
}
@Override
public void killVirus() {
System.out.println("---图像文件:"+name+",进行查杀!");
}
}
class TextFile implements AbstractFile{
private String name;
public TextFile(String name) {
this.name = name;
}
@Override
public void killVirus() {
System.out.println("---文本文件:"+name+",进行查杀!");
}
}
class VideoFile implements AbstractFile{
private String name;
public VideoFile(String name) {
this.name = name;
}
@Override
public void killVirus() {
System.out.println("---视频文件:"+name+",进行查杀!");
}
}
/**
* 文件夹
*/
class Folder implements AbstractFile{
private String name;
//定义容器,用来存放本容器下的子节点
private List<AbstractFile> list = new ArrayList<>();
public Folder(String name) {
this.name = name;
}
public void add(AbstractFile file){
list.add(file);
}
public void remove(AbstractFile file){
list.remove(file);
}
public AbstractFile getChild(int index){
return list.get(index);
}
@Override
public void killVirus() {
System.out.println("---文件夹:"+name+",进行查杀");
for(AbstractFile file : list){
file.killVirus();
}
}
}
public static void main(String[] args) {
AbstractFile f2, f3, f4, f5, f6;
Folder f1 = new Folder("我的收藏");
f2 = new ImageFile("我的大头像.jpg");
f3 = new TextFile("Hello.txt");
f1.add(f2);
f1.add(f3);
Folder f11 = new Folder("电影");
f4 = new VideoFile("笑傲江湖.avi");
f5 = new VideoFile("神雕侠侣.avi");
f11.add(f4);
f11.add(f5);
f1.add(f11);
f1.killVirus();
}
责任链模式: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
package chainOfResponse;
/**
* 抽象类
* Created by huangyichun on 2017/2/8.
*/
public abstract class Leader {
//使用protected让子类能够使用
protected String name;
protected Leader nextLeader;
//设定责任链后序处理者
public Leader(String name) {
this.name = name;
}
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
/**
* 处理请求的核心业务
*
* @param request
*/
public abstract void handleRequest(LeaveRequest request);
}
package chainOfResponse;
/**
* 主任
* Created by huangyichun on 2017/2/8.
*/
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 3) {
System.out.println("员工:" + request.getEmpName() + " 请假" + request.getLeaveDays() + " " +
"理由:" + request.getReason());
System.out.println("主任:" + name + "审批通过");
} else {
if (this.nextLeader != null) {
this.nextLeader.handleRequest(request);
}
}
}
}
package chainOfResponse;
/**
* 经理
* Created by huangyichun on 2017/2/8.
*/
public class Manager extends Leader {
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays() >= 3 && request.getLeaveDays() < 10){
System.out.println("员工:"+request.getEmpName()+" 请假"+request.getLeaveDays()+" " +
"理由:"+request.getReason());
System.out.println("经理:"+name+"审批通过");
}else{
if(this.nextLeader != null){
this.nextLeader.handleRequest(request);
}
}
}
}
package chainOfResponse;
/**
* 总经理
* Created by huangyichun on 2017/2/8.
*/
public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays() >= 10 && request.getLeaveDays() < 30){
System.out.println("员工:"+request.getEmpName()+" 请假"+request.getLeaveDays()+" " +
"理由:"+request.getReason());
System.out.println("总经理:"+name+"审批通过");
}else{
System.out.println("莫非想辞职居然请假"+request.getLeaveDays());
}
}
}
package chainOfResponse;
/**
* 封装请假的基本信息
* Created by huangyichun on 2017/2/8.
*/
public class LeaveRequest {
private String empName;
private int leaveDays;
private String reason;
public LeaveRequest(String empName, int leaveDays, String reason) {
this.empName = empName;
this.leaveDays = leaveDays;
this.reason = reason;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}
package chainOfResponse;
/**
* Created by huangyichun on 2017/2/8.
*/
public class Client {
public static void main(String[] args) {
Leader a = new Director("张三");
Leader b = new Manager("李四");
Leader c = new GeneralManager("王五");
//组织责任链对象的关系
a.setNextLeader(b);
b.setNextLeader(c);
//开始请假操作
LeaveRequest request = new LeaveRequest("Tom",1,"回家过年");
a.handleRequest(request);
}
}