设计模式---结构型
结构型
适配器模式
`将一个类的接口转化为另外一个接口.解决使类之间接口不兼容问题
优点
1.可以让任何两个没有关联的类一起运行。
2.提高了类的复用性、透明度、以及灵活性
3.适配对象,适配库,适配数据
缺点
额外对象的创建,非直接调用,存在一定的开销
过多的使用适配器模式,会让系统变得零乱,不易整体把控。
非必要用适配器模式,就重构最好,若用的话,文档完善
场景
整合第三方SDK diy $.axjax
封装旧接口 vue.computed
适配器与代理模式相似
适配器模式: 提供一个不同的接口
代理模式: 提供一模一样的接口
class Person{
getName(){
return "John";
}
}
class Adapter{
constructor(person){
this.person = person;
}
getFullName(){
return this.person.getName();
}
}
let person = new Person();
let adapter = new Adapter(person);
console.log(adapter.getFullName());
装饰器模式
装饰者模式在不更改源代码情况下,对其进行职责添加。相比于继承装饰器的更轻巧。
通俗的讲我们给心爱的手机上贴膜,带手机壳,贴纸,这些就是对手机的装饰。
优点
装饰类和被装饰类它们之间可以相互独立发展,不会相互耦合,
装饰器模式是继承的一个替代模式,它可以动态的扩展一个实现类的功能。
缺点
多层的装饰会增加复杂度
class Phone{
create(){
console.log("Phone created");
}
}
class Decorator{
constructor(phone){
this.phone = phone;
}
create(){
this.phone.create();
this.addPhoneBox();
this.addPhonePicker();
}
addPhoneBox(){
console.log("Phone box added");
}
addPhonePicker(){
console.log("Phone picker added");
}
}
let phone = new Phone();
let decorator = new Decorator(phone);
decorator.create();
代理模式
优点
代理模式能将代理对象与被调用对象分离,降低了系统的耦合度。
之间起到一个中介作用,这样可以起到保护目标对象的作用
代理对象可以扩展目标对象的功能
通过修改代理对象就可以了,符合开闭原则;
缺点
处理请求速度可能有差别,非直接访问存在开销
// 员工类
class Staff {
constructor(task) {
this.task = task;
}
applyFor(target){
target.receiveAplyFor(this.task)
}
}
// 秘书类 中间人 代理
class Secretary {
constructor() {
this.leader=new Leader();
}
receiveAplyFor(task) {
this.leader.receiveAplyFor(task);
}
}
// 领导类
class Leader{
receiveAplyFor(task) {
console.log('批准: ' + task);
}
}
const staff = new Staff('升职加薪')
staff.applyFor(new Secretary()) // 批准:升职加薪
外观模式
外观模式本质就是封装交互,隐藏系统的复杂性,提供一个可以访问的接口。
由一个将子系统一组的接口集成在一起的高层接口,以提供一个一致的外观,减少外界与多个子系统之间的直接交互,从而更方便的使用子系统。
优点
减少系统相互依赖。
提高灵活性。
提高了安全性
缺点
不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
// 外观模式
function addEvent(el,type,fn){
if(el.addEventlistener){// 高级游览器添加事件DOM API
el.addEventlistener(type,fn,false)
}else if(el.attachEvent){// 低版本游览器的添加事件API
el.attachEvent(`on${type}`,fn)
}else {//其他
el[type] = fn
}
}
二层金字塔
1
2 2 2
桥接模式
桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化。
优点
有助于独立地管理各组成部分, 把抽象化与实现化解耦
提高可扩充性
缺点
大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
//桥接模式(Bridge)
class color{
constructor(name){
this.name = name;
}
}
class shape{
constructor(name,color){
this.name = name;
this.color = color;
}
show(){
console.log(this.name + this.color.name);
}
}
let red = new color('红色');
let yellow = new color('黄色');
let circle = new shape('圆形',red);
let triangle = new shape('三角形',yellow);
circle.show();
triangle.show();
组合模式
组合模式
组合模式就是由一些小的子对象构建出的更大的对象,而这些小的子对象本身可能也是由多个孙对象组合而成的。
组合模式将对象组合成树状结构,以表示“部分-整体”的层次结构。除了用来表示树状结构之外,组合模式的另一个好处就是通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性。
缺点
如果通过组合模式创建了太多的对象,那么这些对象可能会让系统负担不起。
优点
高层模块调用简单,节点可以自由添加
// 组合模式
class Train{
create(){
console.log('创建火车票订单')
}
}
class Hotal{
create(){
console.log('创建酒店订单')
}
}
class TotalOrder{
constructor(){
this.orderList = [];
}
add(order){
this.orderList.push(order);
return this;
}
create(){
this.orderList.forEach(order=>{
order.create();
})
return this;
}
}
let totalOrder = new TotalOrder();
// 可以在购票网站买车票同时也订房间
totalOrder.add(new Train()).add(new Hotal()).create();
享元模式
运用共享技术有效地支持大量细粒度对象的复用。
享元模式的关键是如何区分内部状态和外部状态
内部状态:可以被对象共享,通常不会改变的称为内部状态
外部状态:取决于具体的场景,根据具体的场景变化,并且不能被共享的称为外部状态
优点
大大减少对象的创建,降低系统的内存,使效率提高。
缺点
提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质, 不应该随着内部状态的变化而变化,否则会造成系统的混乱
let id = 0
// 定义内部状态
class Upload {
constructor(uploadType) {
this.uploadType = uploadType
}
// 点击删除时 小于3000直接删除,大于3000通过confirm提示弹窗删除。
delFile(id) {
uploadManager.setExternalState(id,this)
if(this.fileSize < 3000){
return this.dom.parentNode.removeChild(this.dom)
}
if(window.confirm(`确定要删除该文件吗?${this.fileName}`)){
return this.dom.parentNode.removeChild(this.dom)
}
}
}
// 外部状态
class uploadManager {
static uploadDatabase = {}
static add(id, uploadType, fileName, fileSize) {
const filWeightObj = UploadFactory.create(uploadType)
const dom = this.createDom(fileName, fileSize, () => {
filWeightObj.delFile(id)
})
this.uploadDatabase[id] = {
fileName,
fileSize,
dom
}
}
// 创建DOM 并且为button绑定删除事件。
static createDom(fileName, fileSize, fn) {
const dom = document.createElement('div')
dom.innerHTML = `
<span>文件名称:${fileName},文件大小:${fileSize}</span>
<button class="delFile">删除</button>
`
dom.querySelector('.delFile').onclick = fn
document.body.append(dom)
return dom
}
static setExternalState(id, flyWeightObj) {
const uploadData = this.uploadDatabase[id]
for (const key in uploadData) {
if (Object.hasOwnProperty.call(uploadData, key)) {
flyWeightObj[key] = uploadData[key]
}
}
}
}
// 定义一个工厂创建upload对象,如果其内部状态实例对象存在直接返回,反之创建保存并返回。
class UploadFactory {
static createFlyWeightObjs = {}
static create(uploadType) {
if (this.createFlyWeightObjs[uploadType]) {
return this.createFlyWeightObjs[uploadType]
}
return this.createFlyWeightObjs[uploadType] = new Upload(uploadType)
}
}
// 开始加载
const startUpload = (uploadType, files)=>{
for (let i = 0, file; file = files[i++];) {
uploadManager.add(++id, uploadType, file.fileName, file.fileSize)
}
}
startUpload('plugin', [
{fileName: '1.txt',fileSize: 1000},
{fileName: '2.html',fileSize: 3000},
{fileName: '3.txt',fileSize: 5000}
]);
startUpload('flash', [
{fileName: '4.txt',fileSize: 1000},
{fileName: '5.html',fileSize: 3000},
{fileName: '6.txt',fileSize: 5000}
]);

浙公网安备 33010602011771号